diff --git a/libmea-core/jsonrpc/jsonrpcclient.cpp b/libmea-core/jsonrpc/jsonrpcclient.cpp index 6a8938ae..085e8404 100644 --- a/libmea-core/jsonrpc/jsonrpcclient.cpp +++ b/libmea-core/jsonrpc/jsonrpcclient.cpp @@ -243,7 +243,7 @@ void JsonRpcClient::sendRequest(const QVariantMap &request) { QVariantMap newRequest = request; newRequest.insert("token", m_token); - qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson()); +// qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson()); m_connection->sendData(QJsonDocument::fromVariant(newRequest).toJson()); } @@ -278,7 +278,7 @@ void JsonRpcClient::dataReceived(const QByteArray &data) // qWarning() << "Could not parse json data from mea" << data << error.errorString(); return; } - qDebug() << "received response" << m_receiveBuffer.left(splitIndex); +// qDebug() << "received response" << m_receiveBuffer.left(splitIndex); m_receiveBuffer = m_receiveBuffer.right(m_receiveBuffer.length() - splitIndex - 1); if (!m_receiveBuffer.isEmpty()) { staticMetaObject.invokeMethod(this, "dataReceived", Qt::QueuedConnection, Q_ARG(QByteArray, QByteArray())); diff --git a/libmea-core/wifisetup/bluetoothdiscovery.cpp b/libmea-core/wifisetup/bluetoothdiscovery.cpp index 11224ebd..64f99165 100644 --- a/libmea-core/wifisetup/bluetoothdiscovery.cpp +++ b/libmea-core/wifisetup/bluetoothdiscovery.cpp @@ -45,7 +45,7 @@ BluetoothDeviceInfos *BluetoothDiscovery::deviceInfos() return m_deviceInfos; } -void BluetoothDiscovery::setDiscovering(const bool &discovering) +void BluetoothDiscovery::setDiscovering(bool discovering) { m_discovering = discovering; emit discoveringChanged(); diff --git a/libmea-core/wifisetup/bluetoothdiscovery.h b/libmea-core/wifisetup/bluetoothdiscovery.h index 801d09fc..1f7ea2e3 100644 --- a/libmea-core/wifisetup/bluetoothdiscovery.h +++ b/libmea-core/wifisetup/bluetoothdiscovery.h @@ -47,7 +47,7 @@ private: bool m_discovering; - void setDiscovering(const bool &discovering); + void setDiscovering(bool discovering); signals: void discoveringChanged(); diff --git a/libmea-core/wifisetup/wirelessaccesspoints.cpp b/libmea-core/wifisetup/wirelessaccesspoints.cpp index 4decc3fc..b6a8ec9d 100644 --- a/libmea-core/wifisetup/wirelessaccesspoints.cpp +++ b/libmea-core/wifisetup/wirelessaccesspoints.cpp @@ -45,6 +45,7 @@ void WirelessAccesspoints::setWirelessAccessPoints(QList m_wirelessAccessPoints = wirelessAccessPoints; endResetModel(); + emit countChanged(); } int WirelessAccesspoints::rowCount(const QModelIndex &parent) const @@ -95,6 +96,7 @@ void WirelessAccesspoints::clearModel() qDeleteAll(m_wirelessAccessPoints); m_wirelessAccessPoints.clear(); endResetModel(); + emit countChanged(); } void WirelessAccesspoints::setSelectedNetwork(const QString &ssid, const QString &macAdderss) @@ -117,6 +119,7 @@ void WirelessAccesspoints::setSelectedNetwork(const QString &ssid, const QString m_wirelessAccessPoints = wirelessAccessPoints; endResetModel(); + emit countChanged(); } bool WirelessAccesspoints::signalStrengthLessThan(const WirelessAccessPoint *a, const WirelessAccessPoint *b) diff --git a/libmea-core/wifisetup/wirelessaccesspoints.h b/libmea-core/wifisetup/wirelessaccesspoints.h index ceea6a7c..84b40276 100644 --- a/libmea-core/wifisetup/wirelessaccesspoints.h +++ b/libmea-core/wifisetup/wirelessaccesspoints.h @@ -31,6 +31,7 @@ class WirelessAccesspoints : public QAbstractListModel { Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) public: enum BluetoothDeviceInfoRole { WirelessAccesspointRoleSsid = Qt::DisplayRole, @@ -57,6 +58,9 @@ public: static bool signalStrengthLessThan(const WirelessAccessPoint *a, const WirelessAccessPoint *b); +signals: + void countChanged(); + protected: QHash roleNames() const; diff --git a/libmea-core/wifisetup/wirelesssetupmanager.cpp b/libmea-core/wifisetup/wirelesssetupmanager.cpp index 2edcd831..d7746641 100644 --- a/libmea-core/wifisetup/wirelesssetupmanager.cpp +++ b/libmea-core/wifisetup/wirelesssetupmanager.cpp @@ -137,7 +137,6 @@ void WirelessSetupManager::loadNetworks() m_readingResponse = true; m_inputDataStream.clear(); - m_accessPoints->clearModel(); setStatusText("WifiSetupManager: Loading wifi network list..."); setWorking(true); @@ -602,12 +601,18 @@ void WirelessSetupManager::onConnectedChanged() if (!connected()) { // Clean up qDebug() << "WifiSetupManager: Clean up services"; - m_deviceInformationService->deleteLater(); - m_netwokService->deleteLater(); - m_wifiService->deleteLater(); - - if (m_systemService) + if (m_deviceInformationService) { + m_deviceInformationService->deleteLater(); + } + if (m_netwokService) { + m_netwokService->deleteLater(); + } + if (m_wifiService) { + m_wifiService->deleteLater(); + } + if (m_systemService) { m_systemService->deleteLater(); + } m_deviceInformationService = nullptr; m_netwokService = nullptr; diff --git a/mea/resources.qrc b/mea/resources.qrc index acdddf38..b15b0998 100644 --- a/mea/resources.qrc +++ b/mea/resources.qrc @@ -205,5 +205,9 @@ ui/system/AboutNymeaPage.qml ui/images/logs.svg ui/images/plugin.svg + ui/images/nymea-box-setup.svg + ui/images/rpi-setup.svg + ui/images/eye.svg + ui/images/private-browsing.svg diff --git a/mea/ui/BluetoothDiscoveryPage.qml b/mea/ui/BluetoothDiscoveryPage.qml index 7d484d10..e15bd2aa 100644 --- a/mea/ui/BluetoothDiscoveryPage.qml +++ b/mea/ui/BluetoothDiscoveryPage.qml @@ -11,24 +11,53 @@ Page { text: qsTr("Bluetooth discovery") onBackPressed: pageStack.pop() - HeaderButton { - imageSource: Qt.resolvedUrl("images/refresh.svg") - onClicked: Engine.bluetoothDiscovery.start() +// HeaderButton { +// imageSource: Qt.resolvedUrl("images/refresh.svg") +// onClicked: Engine.bluetoothDiscovery.start() +// } + } + + + property bool shouldDiscover: true + + Component.onCompleted: Engine.bluetoothDiscovery.start() + Connections { + target: Engine.bluetoothDiscovery + onDiscoveringChanged: { + print("BT discovery changed:", Engine.bluetoothDiscovery.discovering, shouldDiscover) + if (!Engine.bluetoothDiscovery.discovering && shouldDiscover) { + Engine.bluetoothDiscovery.start(); + } } } - Component.onCompleted: Engine.bluetoothDiscovery.start() + function setupDevice(name, btAddress) { + shouldDiscover = false; + Engine.bluetoothDiscovery.stop() + pageStack.push(Qt.resolvedUrl("BluetoothLoadingPage.qml"), { name: name, address: btAddress } ) + } ColumnLayout { anchors.fill: parent spacing: app.margins - BusyIndicator { - Layout.alignment: Qt.AlignHCenter - running: Engine.bluetoothDiscovery.discovering + RowLayout { + spacing: app.margins + Layout.leftMargin: app.margins + Layout.topMargin: app.margins + Layout.rightMargin: app.rightMargin + Label { + Layout.fillWidth: true + text: qsTr("Searching for %1 boxes via Bluetooth.").arg(app.systemName) + wrapMode: Text.WordWrap + } + + BusyIndicator { + running: Engine.bluetoothDiscovery.discovering + } } - ThinDivider { } + ThinDivider {} ListView { Layout.fillWidth: true @@ -37,42 +66,106 @@ Page { model: Engine.bluetoothDiscovery.deviceInfos clip: true - delegate: ItemDelegate { + delegate: MeaListItemDelegate { width: parent.width - height: app.delegateHeight - - RowLayout { - anchors.verticalCenter: parent.verticalCenter - - Item { - Layout.fillHeight: true - Layout.preferredWidth: height - ColorIcon { - id: image - name: Qt.resolvedUrl("images/bluetooth.svg") - anchors.fill: parent - anchors.margins: app.margins / 2 - } - } - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - anchors.margins: app.margins - Label { - text: model.name - } - Label { - text: model.address - font.pixelSize: app.smallFont - } - } - } + iconName: Qt.resolvedUrl("images/bluetooth.svg") + text: model.name + subText: model.address onClicked: { - print("Start bluetooth connection to", model.name, " --> ", model.address) - Engine.bluetoothDiscovery.stop() - pageStack.push(Qt.resolvedUrl("BluetoothLoadingPage.qml"), { name: model.name, address: model.address } ) + root.setupDevice(model.name, model.address) + } + } + } + + ThinDivider {} + + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.bottomMargin: app.margins + spacing: app.margins + Label { + Layout.fillWidth: true + text: qsTr("Troubles finding your box? Try this!") + } + Button { + text: qsTr("Help") + onClicked: pageStack.push(helpPageComponent) + } + } + } + + Component { + id: helpPageComponent + Page { + id: helpPage + header: GuhHeader { + text: qsTr("Setup help") + onBackPressed: pageStack.pop() + } + + Flickable { + anchors.fill: parent + contentHeight: helpColumn.implicitHeight + + ColumnLayout { + id: helpColumn + width: parent.width + spacing: app.margins + + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins + wrapMode: Text.WordWrap + font.bold: true + text: "Raspberry Pi™" + } + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + wrapMode: Text.WordWrap + text: qsTr("After having installed the nymea community image to your Raspberry Pi, all you need to do is to plug it into a power socket. Note that the Wireless setup will only be available if the Raspberry Pi is not connected to a wired network.") + } + Image { + Layout.preferredWidth: app.iconSize * 8 + Layout.preferredHeight: width * 540 / 800 + sourceSize.width: 800 + sourceSize.height: 540 + fillMode: Image.PreserveAspectFit + Layout.alignment: Qt.AlignHCenter + source: "images/rpi-setup.svg" + } + ThinDivider {} + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + wrapMode: Text.WordWrap + font.bold: true + text: "%1 box".arg(systemName) + } + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + wrapMode: Text.WordWrap + text: qsTr("If you have a %1 box, plug it into a power socket and wait for it to be booted. Once the LED pulses slowly, press the button for 3 seconds until the LED changes.").arg(app.systemName) + } + Image { + Layout.preferredWidth: app.iconSize * 5 + Layout.preferredHeight: width + Layout.bottomMargin: app.margins + sourceSize.width: width + sourceSize.height: width + fillMode: Image.PreserveAspectFit + Layout.alignment: Qt.AlignHCenter + source: "images/nymea-box-setup.svg" + } } } } diff --git a/mea/ui/ConnectPage.qml b/mea/ui/ConnectPage.qml index 296bc55c..9b290155 100644 --- a/mea/ui/ConnectPage.qml +++ b/mea/ui/ConnectPage.qml @@ -70,6 +70,15 @@ Page { onTriggered: pageStack.push(Qt.resolvedUrl("BluetoothDiscoveryPage.qml")) } + IconMenuItem { + iconSource: "../images/private-browsing.svg" + text: qsTr("Demo mode") + onTriggered: { + pageStack.push(connectingPage) + Engine.connection.connect("nymea://83.169.2.242:2222") + } + } + MenuSeparator {} IconMenuItem { @@ -85,7 +94,9 @@ Page { ColumnLayout { Layout.fillWidth: true - Layout.margins: app.margins + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins spacing: app.margins Label { @@ -105,11 +116,7 @@ Page { } } - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - color: Material.accent - } + ThinDivider {} ListView { Layout.fillWidth: true @@ -210,15 +217,42 @@ Page { } - Rectangle { + ThinDivider {} + + Label { Layout.fillWidth: true - Layout.preferredHeight: 1 - color: Material.accent + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + wrapMode: Text.WordWrap + visible: discovery.discoveryModel.count === 0 + text: qsTr("Do you have a %1 box but it's not connected to your network yet? Use the wireless setup to connect it!").arg(app.systemName) + } + Button { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + visible: discovery.discoveryModel.count === 0 + text: qsTr("Start wireless setup") + onClicked: pageStack.push(Qt.resolvedUrl("BluetoothDiscoveryPage.qml")) + } + Button { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.bottomMargin: app.margins + visible: discovery.discoveryModel.count === 0 + text: qsTr("Demo mode (online)") + onClicked: { + pageStack.push(connectingPage) + Engine.connection.connect("nymea://83.169.2.242:2222") + } } RowLayout { Layout.fillWidth: true - Layout.margins: app.margins + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.bottomMargin: app.margins visible: root.haveHosts Label { Layout.fillWidth: true diff --git a/mea/ui/EditDevicesPage.qml b/mea/ui/EditDevicesPage.qml index fef87da6..7762f990 100644 --- a/mea/ui/EditDevicesPage.qml +++ b/mea/ui/EditDevicesPage.qml @@ -10,6 +10,11 @@ Page { header: GuhHeader { text: qsTr("Configure Things") onBackPressed: pageStack.pop() + + HeaderButton { + imageSource: "../images/add.svg" + onClicked: pageStack.push(Qt.resolvedUrl("NewDeviceWizard.qml")) + } } ListView { @@ -18,9 +23,52 @@ Page { delegate: ThingDelegate { interfaces:model.interfaces name: model.name + canDelete: true onClicked: { pageStack.push(Qt.resolvedUrl("devicepages/ConfigureThingPage.qml"), {device: Engine.deviceManager.devices.get(index)}) } + onDeleteClicked: { + Engine.deviceManager.removeDevice(Engine.deviceManager.devices.get(index).id) + } } } + + ColumnLayout { + anchors { left: parent.left; right: parent.right; margins: app.margins } + anchors.verticalCenter: parent.verticalCenter + spacing: app.margins * 2 + visible: Engine.deviceManager.devices.count === 0 && !Engine.deviceManager.fetchingData + Label { + text: qsTr("There are no things set up yet.") + font.pixelSize: app.largeFont + Layout.fillWidth: true + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + color: app.guhAccent + } + Label { + text: qsTr("In order for your %1 box to be useful, go ahead and add some things.").arg(app.systemName) + Layout.fillWidth: true + Layout.maximumWidth: 400 + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + } + Image { + source: "../guh-logo.svg" + Layout.preferredWidth: app.iconSize * 5 + Layout.preferredHeight: width + Layout.alignment: Qt.AlignHCenter + sourceSize.width: app.iconSize * 5 + sourceSize.height: app.iconSize * 5 + } + Button { + Layout.fillWidth: true + Layout.maximumWidth: 400 + Layout.alignment: Qt.AlignHCenter + text: qsTr("Add a thing") + onClicked: pageStack.push(Qt.resolvedUrl("NewDeviceWizard.qml")) + } + } + } diff --git a/mea/ui/MagicPage.qml b/mea/ui/MagicPage.qml index f9de8c31..48c39f8f 100644 --- a/mea/ui/MagicPage.qml +++ b/mea/ui/MagicPage.qml @@ -13,22 +13,26 @@ Page { HeaderButton { imageSource: Qt.resolvedUrl("images/add.svg") onClicked: { - d.editRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.createNewRule() }); - d.editRulePage.StackView.onRemoved.connect(function() { - d.editRulePage.rule.destroy() - d.editRulePage = null; - }) - d.editRulePage.onAccept.connect(function() { - d.editRulePage.busy = true; - Engine.ruleManager.addRule(d.editRulePage.rule); - }) - d.editRulePage.onCancel.connect(function() { - pageStack.pop(); - }) + addRule() } } } + function addRule() { + d.editRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.createNewRule() }); + d.editRulePage.StackView.onRemoved.connect(function() { + d.editRulePage.rule.destroy() + d.editRulePage = null; + }) + d.editRulePage.onAccept.connect(function() { + d.editRulePage.busy = true; + Engine.ruleManager.addRule(d.editRulePage.rule); + }) + d.editRulePage.onCancel.connect(function() { + pageStack.pop(); + }) + } + QtObject { id: d property var editRulePage: null @@ -88,6 +92,39 @@ Page { } } + ColumnLayout { + anchors { left: parent.left; right: parent.right; margins: app.margins } + anchors.verticalCenter: parent.verticalCenter + spacing: app.margins * 2 + visible: Engine.ruleManager.rules.count === 0 + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + text: qsTr("There is no magic set up yet.") + wrapMode: Text.WordWrap + color: app.guhAccent + font.pixelSize: app.largeFont + } + Label { + text: qsTr("Add some using the wizard stick!") + Layout.fillWidth: true + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + } + AbstractButton { + Layout.preferredHeight: app.iconSize * 4 + Layout.preferredWidth: height + Layout.alignment: Qt.AlignHCenter + + ColorIcon { + anchors.fill: parent + name: "../images/magic.svg" + } + + onClicked: addRule() + } + } + Component { id: errorDialog ErrorDialog {} diff --git a/mea/ui/MainPage.qml b/mea/ui/MainPage.qml index f54bc28c..557c064b 100644 --- a/mea/ui/MainPage.qml +++ b/mea/ui/MainPage.qml @@ -44,12 +44,7 @@ Page { text: qsTr("Configure things") onTriggered: pageStack.push(Qt.resolvedUrl("EditDevicesPage.qml")) } - IconMenuItem { - iconSource: "../images/add.svg" - text: qsTr("Add a new thing") - onTriggered: pageStack.push(Qt.resolvedUrl("NewDeviceWizard.qml")) - } - MenuSeparator {} +// MenuSeparator {} IconMenuItem { iconSource: "../images/magic.svg" text: qsTr("Magic") @@ -128,8 +123,9 @@ Page { } ColumnLayout { - anchors { left: parent.left; right: parent.right; top: parent.top; margins: app.margins } - spacing: app.margins + anchors { left: parent.left; right: parent.right; margins: app.margins } + anchors.verticalCenter: parent.verticalCenter + spacing: app.margins * 2 visible: Engine.deviceManager.devices.count === 0 && !Engine.deviceManager.fetchingData Label { text: qsTr("Welcome to %1!").arg(app.systemName) @@ -140,11 +136,28 @@ Page { color: app.guhAccent } Label { - text: qsTr("There are no things set up yet. You can start with adding your things by using the menu on the upper left and selecting \"Add a new thing\".") + text: qsTr("There are no things set up yet. In order for your %1 box to be useful, go ahead and add some things.").arg(app.systemName) Layout.fillWidth: true + Layout.maximumWidth: 400 + Layout.alignment: Qt.AlignHCenter wrapMode: Text.WordWrap horizontalAlignment: Text.AlignHCenter } + Image { + source: "../guh-logo.svg" + Layout.preferredWidth: app.iconSize * 5 + Layout.preferredHeight: width + Layout.alignment: Qt.AlignHCenter + sourceSize.width: app.iconSize * 5 + sourceSize.height: app.iconSize * 5 + } + Button { + Layout.fillWidth: true + Layout.maximumWidth: 400 + Layout.alignment: Qt.AlignHCenter + text: qsTr("Add a thing") + onClicked: pageStack.push(Qt.resolvedUrl("NewDeviceWizard.qml")) + } } } } diff --git a/mea/ui/Mea.qml b/mea/ui/Mea.qml index 05de6763..d7a7c25e 100644 --- a/mea/ui/Mea.qml +++ b/mea/ui/Mea.qml @@ -10,7 +10,7 @@ ApplicationWindow { visible: true width: 360 height: 580 - visibility: settings.viewMode + visibility: ApplicationWindow.Maximized font: Qt.application.font title: appName @@ -26,7 +26,7 @@ ApplicationWindow { property var settings: Settings { property string lastConnectedHost: "" - property int viewMode: ApplicationWindow.Maximized + property alias viewMode: app.visibility property bool returnToHome: false property bool darkTheme: false property string graphStyle: "bars" diff --git a/mea/ui/NewDeviceWizard.qml b/mea/ui/NewDeviceWizard.qml index 88a1a3a9..86d483e2 100644 --- a/mea/ui/NewDeviceWizard.qml +++ b/mea/ui/NewDeviceWizard.qml @@ -72,20 +72,9 @@ Page { model: VendorsProxy { vendors: Engine.deviceManager.vendors } - delegate: ItemDelegate { + delegate: MeaListItemDelegate { width: parent.width - height: app.delegateHeight - contentItem: RowLayout { - Label { - Layout.fillWidth: true - text: model.displayName - } - Image { - source: "images/next.svg" - Layout.preferredHeight: parent.height - Layout.preferredWidth: height - } - } + text: model.displayName onClicked: { d.vendorId = model.id diff --git a/mea/ui/WirelessControlerPage.qml b/mea/ui/WirelessControlerPage.qml index d038c4b8..4d937e63 100644 --- a/mea/ui/WirelessControlerPage.qml +++ b/mea/ui/WirelessControlerPage.qml @@ -2,9 +2,8 @@ import QtQuick 2.4 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.2 import QtQuick.Controls.Material 2.1 - -import "components" import Mea 1.0 +import "components" Page { id: root @@ -14,30 +13,17 @@ Page { property QtObject networkManger header: GuhHeader { - text: qsTr("Wireless network") + text: qsTr("%1 box network setup").arg(app.systemName) onBackPressed: { pageStack.pop() pageStack.pop() } - - HeaderButton { - imageSource: Qt.resolvedUrl("images/refresh.svg") - onClicked: networkManger.manager.loadNetworks() - } - - HeaderButton { - imageSource: Qt.resolvedUrl("images/settings.svg") - onClicked: pageStack.push(settingsPage) - } - } - Component.onCompleted: networkManger.manager.loadNetworks() - Connections { target: networkManger.manager onErrorOccured: { - print("Error occured", errorMessage) + print("Error occurred", errorMessage) var errorDialog = Qt.createComponent(Qt.resolvedUrl("components/ErrorDialog.qml")); var popup = errorDialog.createObject(app, {text: errorMessage}) popup.open() @@ -51,14 +37,49 @@ Page { } } + Timer { + id: loadNetworksTimer + interval: networkManger.manager.accessPoints.count === 0 ? 1000 : 5000 + running: networkManger.manager.networkingEnabled && networkManger.manager.wirelessEnabled + repeat: true + onTriggered: { + networkManger.manager.loadNetworks() + } + } + ColumnLayout { anchors.fill: parent visible: networkManger.manager.initialized - Label { - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignHCenter - text:{ + MeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/info.svg" + text: qsTr("About this %1 box").arg(app.systemName) + onClicked: pageStack.push(infoPage) + } + + SwitchDelegate { + Layout.fillWidth: true + text: qsTr("Wired network") + checked: networkManger.manager.networkingEnabled + onClicked: networkManger.manager.enableNetworking(checked) + } + + SwitchDelegate { + Layout.fillWidth: true + enabled: networkManger.manager.networkingEnabled + text: qsTr("Wireless network") + checked: networkManger.manager.wirelessEnabled + onClicked: { + networkManger.manager.enableWireless(checked) + } + } + + MeaListItemDelegate { + Layout.fillWidth: true + progressive: false + text: qsTr("Networking status") + subText: { switch (networkManger.manager.networkStatus) { case WirelessSetupManager.NetworkStatusUnknown: return qsTr("Unknown status."); @@ -77,137 +98,93 @@ Page { case WirelessSetupManager.NetworkStatusGlobal: return qsTr("Online."); } + return "???" } } - BusyIndicator { - Layout.alignment: Qt.AlignHCenter - running: networkManger.manager.working + ThinDivider { + visible: networkManger.manager.wirelessEnabled } - ThinDivider { } - ListView { Layout.fillWidth: true Layout.fillHeight: true + visible: networkManger.manager.wirelessEnabled model: networkManger.manager.accessPoints clip: true - delegate: ItemDelegate { - width: parent.width - height: model.selectedNetwork ? app.delegateHeight * 1.5 : app.delegateHeight + BusyIndicator { + anchors.centerIn: parent + running: networkManger.manager.working + } - Rectangle { - anchors.fill: parent - color: guhAccent - visible: model.selectedNetwork + delegate: MeaListItemDelegate { + width: parent.width + text: model.ssid + subText: { + if (!model.selectedNetwork) { + return ""; + } + switch (networkManger.manager.wirelessStatus) { + case WirelessSetupManager.WirelessStatusUnknown: + return qsTr("Unknown status."); + case WirelessSetupManager.WirelessStatusUnmanaged: + return qsTr("Network unmanaged."); + case WirelessSetupManager.WirelessStatusUnavailable: + return qsTr("Network unavailable."); + case WirelessSetupManager.WirelessStatusDisconnected: + return qsTr("Disconnected."); + case WirelessSetupManager.WirelessStatusPrepare: + return qsTr("Prepare connection..."); + case WirelessSetupManager.WirelessStatusConfig: + return qsTr("Configure network..."); + case WirelessSetupManager.WirelessStatusNeedAuth: + return qsTr("Authentication needed"); + case WirelessSetupManager.WirelessStatusIpConfig: + return qsTr("Configuration IP..."); + case WirelessSetupManager.WirelessStatusIpCheck: + return qsTr("Check IP..."); + case WirelessSetupManager.WirelessStatusSecondaries: + return qsTr("Secondaries..."); + case WirelessSetupManager.WirelessStatusActivated: + return qsTr("Network connected."); + case WirelessSetupManager.WirelessStatusDeactivating: + return qsTr("Network disconnecting..."); + case WirelessSetupManager.WirelessStatusFailed: + return qsTr("Network connection failed."); + } } - RowLayout { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.right: parent.right + iconColor: model.selectedNetwork ? app.guhAccent : "#808080" + iconName: { + if (model.protected) { + if (model.signalStrength <= 25) + return Qt.resolvedUrl("images/nm-signal-25-secure.svg") - Item { - Layout.preferredHeight: app.delegateHeight - Layout.preferredWidth: height + if (model.signalStrength <= 50) + return Qt.resolvedUrl("images/nm-signal-50-secure.svg") - ColorIcon { - id: image - anchors.fill: parent - anchors.margins: app.margins / 2 - name: { - if (model.protected) { - if (model.signalStrength <= 25) - return Qt.resolvedUrl("images/nm-signal-25-secure.svg") + if (model.signalStrength <= 75) + return Qt.resolvedUrl("images/nm-signal-75-secure.svg") - if (model.signalStrength <= 50) - return Qt.resolvedUrl("images/nm-signal-50-secure.svg") + if (model.signalStrength <= 100) + return Qt.resolvedUrl("images/nm-signal-100-secure.svg") - if (model.signalStrength <= 75) - return Qt.resolvedUrl("images/nm-signal-75-secure.svg") + } else { - if (model.signalStrength <= 100) - return Qt.resolvedUrl("images/nm-signal-100-secure.svg") + if (model.signalStrength <= 25) + return Qt.resolvedUrl("images/nm-signal-25.svg") - } else { + if (model.signalStrength <= 50) + return Qt.resolvedUrl("images/nm-signal-50.svg") - if (model.signalStrength <= 25) - return Qt.resolvedUrl("images/nm-signal-25.svg") + if (model.signalStrength <= 75) + return Qt.resolvedUrl("images/nm-signal-75.svg") - if (model.signalStrength <= 50) - return Qt.resolvedUrl("images/nm-signal-50.svg") + if (model.signalStrength <= 100) + return Qt.resolvedUrl("images/nm-signal-100.svg") - if (model.signalStrength <= 75) - return Qt.resolvedUrl("images/nm-signal-75.svg") - - if (model.signalStrength <= 100) - return Qt.resolvedUrl("images/nm-signal-100.svg") - - } - } - } - } - - Label { - Layout.alignment: Qt.AlignVCenter - text: model.signalStrength + "%" - } - - ColumnLayout { - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - Label { - text: model.ssid - } - - Label { - text: model.macAddress - font.pixelSize: app.smallFont - } - - Label { - text: { - switch (networkManger.manager.wirelessStatus) { - case WirelessSetupManager.WirelessStatusUnknown: - return qsTr("Unknown status."); - case WirelessSetupManager.WirelessStatusUnmanaged: - return qsTr("Network unmanaged."); - case WirelessSetupManager.WirelessStatusUnavailable: - return qsTr("Network unavailable."); - case WirelessSetupManager.WirelessStatusDisconnected: - return qsTr("Disconnected."); - case WirelessSetupManager.WirelessStatusPrepare: - return qsTr("Prepare connection..."); - case WirelessSetupManager.WirelessStatusConfig: - return qsTr("Configure network..."); - case WirelessSetupManager.WirelessStatusNeedAuth: - return qsTr("Authentication needed"); - case WirelessSetupManager.WirelessStatusIpConfig: - return qsTr("Configuration IP..."); - case WirelessSetupManager.WirelessStatusIpCheck: - return qsTr("Check IP..."); - case WirelessSetupManager.WirelessStatusSecondaries: - return qsTr("Secondaries..."); - case WirelessSetupManager.WirelessStatusActivated: - return qsTr("Network connected."); - case WirelessSetupManager.WirelessStatusDeactivating: - return qsTr("Network disconnecting..."); - case WirelessSetupManager.WirelessStatusFailed: - return qsTr("Network connection failed."); - } - } - - font.pixelSize: app.smallFont - visible: model.selectedNetwork - } - } - - Button { - text: qsTr("Disconnect") - visible: model.selectedNetwork && networkManger.manager.wirelessStatus === WirelessSetupManager.WirelessStatusActivated - onClicked: networkManger.manager.disconnectWirelessNetwork() } } @@ -234,40 +211,49 @@ Page { } ColumnLayout { - anchors.fill: parent - anchors.margins: app.margins + anchors { left: parent.left; top: parent.top; right: parent.right } Label { wrapMode: Text.WordWrap - font.pixelSize: app.largeFont Layout.fillWidth: true - text: ssid + " (" + macAddress + ")" + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Layout.topMargin: app.margins + text: qsTr("Please enter the password for the Wifi network.") } - Label { - wrapMode: Text.WordWrap + MeaListItemDelegate { Layout.fillWidth: true - text: qsTr("Please enter the password for the Wifi network.") + text: ssid + subText: macAddress + progressive: false } RowLayout { Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + spacing: app.margins TextField { id: passwordTextField Layout.fillWidth: true echoMode: TextInput.Password } - - Button { - text: qsTr("Show password") - onClicked: { - if (passwordTextField.echoMode === TextInput.Normal) { - text = qsTr("Show password") - passwordTextField.echoMode = TextInput.Password - } else { - text = qsTr("Hide password") - passwordTextField.echoMode = TextInput.Normal + ColorIcon { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: app.iconSize + name: "../images/eye.svg" + color: passwordTextField.echoMode === TextInput.Normal ? app.guhAccent : keyColor + MouseArea { + anchors.fill: parent + anchors.margins: -app.margins / 2 + onClicked: { + if (passwordTextField.echoMode === TextInput.Normal) { + passwordTextField.echoMode = TextInput.Password + } else { + passwordTextField.echoMode = TextInput.Normal + } } } } @@ -275,6 +261,8 @@ Page { Button { Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins text: qsTr("Connect") onPressed: { networkManger.manager.connectWirelessNetwork(ssid, passwordTextField.text) @@ -282,130 +270,52 @@ Page { pageStack.pop() } } - } } } - Component { - id: settingsPage + id: infoPage Page { id: root header: GuhHeader { - text: qsTr("Network settings") + text: qsTr("Box information") onBackPressed: pageStack.pop() } ColumnLayout { - anchors.fill: parent - anchors.margins: app.margins + anchors { left: parent.left; top: parent.top; right: parent.right } - RowLayout { - anchors.margins: app.margins + MeaListItemDelegate { Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("Networking") - } - - Switch { - id: networkingSwitch - checked: networkManger.manager.networkingEnabled - onCheckedChanged: networkManger.manager.enableNetworking(checked) - } + progressive: false + text: qsTr("System UUID") + subText: networkManger.manager.modelNumber } - - RowLayout { - anchors.margins: app.margins + MeaListItemDelegate { Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("Wireless networking") - } - - Switch { - id: wirelessNetworkingSwitch - checked: networkManger.manager.wirelessEnabled - onCheckedChanged: networkManger.manager.enableWireless(checked) - } + progressive: false + text: qsTr("Manufacturer") + subText: networkManger.manager.manufacturer } - - ThinDivider { } - - Label { + MeaListItemDelegate { Layout.fillWidth: true - text: qsTr("Bluetooth device information") + progressive: false + text: qsTr("Software revision") + subText: networkManger.manager.softwareRevision } - - ThinDivider { } - - RowLayout { - anchors.margins: app.margins + MeaListItemDelegate { Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("System UUID") - } - - Label { - text: networkManger.manager.modelNumber - } + progressive: false + text: qsTr("Firmware revision") + subText: networkManger.manager.firmwareRevision } - - RowLayout { + MeaListItemDelegate { Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("Manufacturer") - } - Label { - text: networkManger.manager.manufacturer - } - } - - RowLayout { - anchors.margins: app.margins - Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("Software revision") - } - Label { - text: networkManger.manager.softwareRevision - } - } - - RowLayout { - anchors.margins: app.margins - Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("Firmware revision") - } - Label { - text: networkManger.manager.firmwareRevision - } - } - - RowLayout { - anchors.margins: app.margins - Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: qsTr("Hardware revision") - } - Label { - text: networkManger.manager.hardwareRevision - } + progressive: false + text: qsTr("Hardware revision") + subText: networkManger.manager.hardwareRevision } } } diff --git a/mea/ui/components/MeaListItemDelegate.qml b/mea/ui/components/MeaListItemDelegate.qml index 55131509..2601ed8b 100644 --- a/mea/ui/components/MeaListItemDelegate.qml +++ b/mea/ui/components/MeaListItemDelegate.qml @@ -48,7 +48,7 @@ SwipeDelegate { } ColorIcon { - Layout.preferredHeight: app.iconSize + Layout.preferredHeight: app.iconSize * .6 Layout.preferredWidth: height name: "../images/next.svg" visible: root.progressive diff --git a/mea/ui/images/eye.svg b/mea/ui/images/eye.svg new file mode 100644 index 00000000..0be90595 --- /dev/null +++ b/mea/ui/images/eye.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/mea/ui/images/nymea-box-setup.svg b/mea/ui/images/nymea-box-setup.svg new file mode 100644 index 00000000..fed9f80f --- /dev/null +++ b/mea/ui/images/nymea-box-setup.svg @@ -0,0 +1,222 @@ + + + + + + image/svg+xml + + Asset 31 + + + + + + Asset 31 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mea/ui/images/private-browsing.svg b/mea/ui/images/private-browsing.svg new file mode 100644 index 00000000..8f7e0742 --- /dev/null +++ b/mea/ui/images/private-browsing.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/mea/ui/images/rpi-setup.svg b/mea/ui/images/rpi-setup.svg new file mode 100644 index 00000000..aad7040d --- /dev/null +++ b/mea/ui/images/rpi-setup.svg @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + looks like raspberry pi printed circuit board + 2013-10-11T20:32:48 + Any similarity to Raspberry pi is not intended ;-) + https://openclipart.org/detail/184791/looks-like-raspberry-pi-printed-circuit-board-by-mawoki-184791 + + + mawoki + + + + + electronic components + pcb + pi + printed circuit board + raspberry + raspberry pi + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mea/ui/magic/DeviceRulesPage.qml b/mea/ui/magic/DeviceRulesPage.qml index be0852e6..6032ea3e 100644 --- a/mea/ui/magic/DeviceRulesPage.qml +++ b/mea/ui/magic/DeviceRulesPage.qml @@ -33,7 +33,7 @@ Page { }) d.editRulePage.onAccept.connect(function() { d.editRulePage.busy = true; - Engine.ruleManager.addRule(page.rule); + Engine.ruleManager.addRule(d.editRulePage.rule); }) d.editRulePage.onCancel.connect(function() { pageStack.pop(); @@ -87,23 +87,14 @@ Page { filterDeviceId: root.device.id } - delegate: SwipeDelegate { + delegate: MeaListItemDelegate { width: parent.width - contentItem: RowLayout { - spacing: app.margins - ColorIcon { - height: app.iconSize - width: height - name: "../images/magic.svg" - color: !model.enabled ? "red" : (model.active ? app.guhAccent : "grey") - } - - Label { - Layout.fillWidth: true - text: model.name - } - } + iconName: "../images/magic.svg" + iconColor: !model.enabled ? "red" : (model.active ? app.guhAccent : "grey") + text: model.name + canDelete: true + onDeleteClicked: Engine.ruleManager.removeRule(model.id) onClicked: { d.editRulePage = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: rulesFilterModel.get(index).clone() }) d.editRulePage.StackView.onRemoved.connect(function() { @@ -118,19 +109,6 @@ Page { }) } - swipe.right: Item { - height: ruleDelegate.height - width: height - anchors.right: parent.right - ColorIcon { - anchors.fill: parent - anchors.margins: app.margins - name: "../images/delete.svg" - color: "red" - } - SwipeDelegate.onClicked: Engine.ruleManager.removeRule(model.id) - } - } } @@ -146,6 +124,7 @@ Page { horizontalAlignment: Text.AlignHCenter text: qsTr("There's no magic involving %1.").arg(root.device.name) font.pixelSize: app.largeFont + color: app.guhAccent } Label { width: parent.width