diff --git a/src/ui/MainWindow.qml b/src/ui/MainWindow.qml index 103ed6069b04a5688af73718a5c4d37ac400cd23..38bfa9f3b1cc14fb23397740729e5e11e3135047 100644 --- a/src/ui/MainWindow.qml +++ b/src/ui/MainWindow.qml @@ -25,11 +25,12 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtPositioning 5.2 -import QGroundControl 1.0 -import QGroundControl.Palette 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.FlightDisplay 1.0 -import QGroundControl.ScreenTools 1.0 +import QGroundControl 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.MultiVehicleManager 1.0 /// Qml for MainWindow Item { @@ -40,15 +41,20 @@ Item { QGCPalette { id: __qgcPal; colorGroupEnabled: true } - property real tbHeight: ScreenTools.isMobile ? (ScreenTools.isTinyScreen ? (mainWindow.width * 0.0666) : (mainWindow.width * 0.05)) : ScreenTools.defaultFontPixelSize * 4 - property int tbCellHeight: tbHeight * 0.75 - property real tbSpacing: ScreenTools.isMobile ? width * 0.00824 : 9.54 - property real tbButtonWidth: tbCellHeight * 1.3 - property real availableHeight: height - tbHeight - property real menuButtonWidth: (tbButtonWidth * 2) + (tbSpacing * 4) + 1 + property real tbHeight: ScreenTools.isMobile ? (ScreenTools.isTinyScreen ? (mainWindow.width * 0.0666) : (mainWindow.width * 0.05)) : ScreenTools.defaultFontPixelSize * 4 + property int tbCellHeight: tbHeight * 0.75 + property real tbSpacing: ScreenTools.isMobile ? width * 0.00824 : 9.54 + property real tbButtonWidth: tbCellHeight * 1.3 + property real availableHeight: height - tbHeight + property real menuButtonWidth: (tbButtonWidth * 2) + (tbSpacing * 4) + 1 - property var defaultPosition: QtPositioning.coordinate(37.803784, -122.462276) - property var tabletPosition: defaultPosition + property var defaultPosition: QtPositioning.coordinate(37.803784, -122.462276) + property var tabletPosition: defaultPosition + + property var currentPopUp: null + property real currentCenterX: 0 + property var activeVehicle: multiVehicleManager.activeVehicle + property string formatedMessage: activeVehicle ? activeVehicle.formatedMessage : "" Connections { @@ -129,6 +135,42 @@ Item { flightView.interactive = enabled } + onFormatedMessageChanged: { + if(messageArea.visible) { + messageText.append(formatedMessage) + //-- Hack to scroll down + messageFlick.flick(0,-500) + } + } + + function showMessageArea() { + if(currentPopUp) { + currentPopUp.close() + } + if(multiVehicleManager.activeVehicleAvailable) { + messageText.text = activeVehicle.formatedMessages + //-- Hack to scroll to last message + for (var i = 0; i < activeVehicle.messageCount; i++) + messageFlick.flick(0,-5000) + activeVehicle.resetMessages() + } else { + messageText.text = "No Messages" + } + currentPopUp = messageArea + messageArea.visible = true + mainWindow.setMapInteractive(false) + } + + function showPopUp(dropItem, centerX) { + if(currentPopUp) { + currentPopUp.close() + } + indicatorDropdown.centerX = centerX + indicatorDropdown.sourceComponent = dropItem + indicatorDropdown.visible = true + currentPopUp = indicatorDropdown + } + //-- Left Settings Menu Loader { id: leftPanel @@ -176,4 +218,83 @@ Item { visible: false } + //------------------------------------------------------------------------- + //-- Dismiss Pop Up Messages + MouseArea { + visible: currentPopUp != null + enabled: currentPopUp != null + anchors.fill: parent + onClicked: { + currentPopUp.close() + } + } + + //------------------------------------------------------------------------- + //-- Indicator Drop Down Info + Loader { + id: indicatorDropdown + visible: false + property real centerX: 0 + function close() { + sourceComponent = null + mainWindow.currentPopUp = null + } + } + + //------------------------------------------------------------------------- + //-- System Message Area + Rectangle { + id: messageArea + + function close() { + currentPopUp = null + messageText.text = "" + mainWindow.setMapInteractive(true) + messageArea.visible = false + } + + width: mainWindow.width * 0.5 + height: mainWindow.height * 0.5 + color: Qt.rgba(0,0,0,0.75) + visible: false + radius: ScreenTools.defaultFontPixelHeight * 0.5 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + anchors.topMargin: tbHeight + ScreenTools.defaultFontPixelHeight + Flickable { + id: messageFlick + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.fill: parent + contentHeight: messageText.height + contentWidth: messageText.width + boundsBehavior: Flickable.StopAtBounds + pixelAligned: true + clip: true + TextEdit { + id: messageText + readOnly: true + textFormat: TextEdit.RichText + color: "white" + } + } + //-- Dismiss System Message + Image { + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.top: parent.top + anchors.right: parent.right + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: ScreenTools.defaultFontPixelHeight * 1.5 + source: "/res/XDelete.svg" + fillMode: Image.PreserveAspectFit + mipmap: true + smooth: true + MouseArea { + anchors.fill: parent + onClicked: { + messageArea.close() + } + } + } + } + } diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index 85104219fa116d62b7a7ee5cbc0a1bdbacd36aed..c02adfcf666a5fc65963e22e19ee59190806bade 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -28,12 +28,12 @@ This file is part of the QGROUNDCONTROL project */ import QtQuick 2.5 +import QtQuick.Layouts 1.2 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 import QGroundControl 1.0 import QGroundControl.Controls 1.0 -import QGroundControl.FactControls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.MultiVehicleManager 1.0 import QGroundControl.ScreenTools 1.0 @@ -51,8 +51,6 @@ Rectangle { property bool isBackgroundDark: true property bool opaqueBackground: false - property string formatedMessage: activeVehicle ? activeVehicle.formatedMessage : "" - /* Dev System (Mac OS) @@ -149,28 +147,6 @@ Rectangle { MainToolBarController { id: _controller } - onFormatedMessageChanged: { - if(messageArea.visible) { - messageText.append(formatedMessage) - //-- Hack to scroll down - messageFlick.flick(0,-500) - } - } - - function showMessageArea() { - if(multiVehicleManager.activeVehicleAvailable) { - messageText.text = activeVehicle.formatedMessages - //-- Hack to scroll to last message - for (var i = 0; i < activeVehicle.messageCount; i++) - messageFlick.flick(0,-5000) - activeVehicle.resetMessages() - } else { - messageText.text = "No Messages" - } - messageArea.visible = true - mainWindow.setMapInteractive(false) - } - function showToolbarMessage(message) { toolBarMessage.text = message toolBarMessageArea.visible = true @@ -180,6 +156,21 @@ Rectangle { return (multiVehicleManager.activeVehicleAvailable && activeVehicle.heartbeatTimeout === 0); } + function getBatteryColor() { + if(activeVehicle) { + if(activeVehicle.batteryPercent > 75) { + return colorGreen + } + if(activeVehicle.batteryPercent > 50) { + return colorOrange + } + if(activeVehicle.batteryPercent > 0.1) { + return colorRed + } + } + return colorGrey + } + Component.onCompleted: { //-- TODO: Get this from the actual state flyButton.checked = true @@ -192,6 +183,113 @@ Rectangle { onShowSetupView:{ setupButton.checked = true } } + //--------------------------------------------- + // Battery Info + Component { + id: batteryInfo + Rectangle { + color: Qt.rgba(0,0,0,0.75) + width: battCol.width + ScreenTools.defaultFontPixelWidth * 3 + height: battCol.height + ScreenTools.defaultFontPixelHeight * 2 + radius: ScreenTools.defaultFontPixelHeight * 0.5 + Column { + id: battCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: Math.max(battGrid.width, battLabel.width) + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.centerIn: parent + QGCLabel { + id: battLabel + text: (activeVehicle && (activeVehicle.batteryVoltage > 0)) ? "Battery Status" : "Battery Data Unavailable" + font.weight:Font.DemiBold + anchors.horizontalCenter: parent.horizontalCenter + } + GridLayout { + id: battGrid + visible: (activeVehicle && (activeVehicle.batteryVoltage > 0)) + anchors.margins: ScreenTools.defaultFontPixelHeight + columnSpacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + columns: 2 + QGCLabel { + text: "Voltage:" + } + QGCLabel { + text: activeVehicle ? (activeVehicle.batteryVoltage.toFixed(1) + " V") : "N/A" + color: getBatteryColor() + } + // TODO: What "controller" provides "Facts"? + /* + QGCLabel { + text: "Cell Voltage:" + } + QGCLabel { + text: (activeVehicle.batteryVoltage / controller.getParameterFact(-1, "BAT_N_CELLS").value) + "V" + color: getBatteryColor() + } + */ + QGCLabel { + text: "Accumulated Consumption:" + } + QGCLabel { + text: activeVehicle ? (activeVehicle.batteryConsumed + " mA") : "N/A" + color: getBatteryColor() + } + } + } + Component.onCompleted: { + var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) + x = pos.x + y = pos.y + ScreenTools.defaultFontPixelHeight + } + } + } + + //--------------------------------------------- + // RC RSSI Info + Component { + id: rcRSSIInfo + Rectangle { + color: Qt.rgba(0,0,0,0.75) + width: battCol.width + ScreenTools.defaultFontPixelWidth * 3 + height: battCol.height + ScreenTools.defaultFontPixelHeight * 2 + radius: ScreenTools.defaultFontPixelHeight * 0.5 + Column { + id: battCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: Math.max(battGrid.width, rssiLabel.width) + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.centerIn: parent + QGCLabel { + id: rssiLabel + text: "RC RSSI Status" + font.weight:Font.DemiBold + anchors.horizontalCenter: parent.horizontalCenter + } + GridLayout { + id: battGrid + anchors.margins: ScreenTools.defaultFontPixelHeight + columnSpacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + columns: 2 + QGCLabel { + text: "RSSI:" + } + QGCLabel { + text: activeVehicle ? (activeVehicle.rcRSSI + "%") : 0 + } + } + } + Component.onCompleted: { + var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) + x = pos.x + y = pos.y + ScreenTools.defaultFontPixelHeight + } + } + } + + //--------------------------------------------- + // Toolbar Row Row { id: viewRow height: mainWindow.tbCellHeight @@ -287,55 +385,6 @@ Rectangle { } } - //------------------------------------------------------------------------- - //-- System Message Area - Rectangle { - id: messageArea - width: mainWindow.width * 0.5 - height: mainWindow.height * 0.5 - anchors.top: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - color: Qt.rgba(0,0,0,0.75) - visible: false - radius: ScreenTools.defaultFontPixelHeight * 0.5 - Flickable { - id: messageFlick - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.fill: parent - contentHeight: messageText.height - contentWidth: messageText.width - boundsBehavior: Flickable.StopAtBounds - pixelAligned: true - clip: true - TextEdit { - id: messageText - readOnly: true - textFormat: TextEdit.RichText - color: "white" - } - } - //-- Dismiss System Message - Image { - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.top: parent.top - anchors.right: parent.right - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: ScreenTools.defaultFontPixelHeight * 1.5 - source: "/res/XDelete.svg" - fillMode: Image.PreserveAspectFit - mipmap: true - smooth: true - MouseArea { - anchors.fill: parent - onClicked: { - messageText.text = "" - messageArea.visible = false - mainWindow.setMapInteractive(true) - } - } - } - } - QGCLabel { id: connectionStatus visible: (_controller.connectionCount > 0 && multiVehicleManager.activeVehicleAvailable && activeVehicle.heartbeatTimeout != 0) diff --git a/src/ui/toolbar/MainToolBarIndicators.qml b/src/ui/toolbar/MainToolBarIndicators.qml index 4637a9d6c470bb6d8d8969dd666c09a8000eec61..ae875535c4b2a3b6985b71a959007297769a9905 100644 --- a/src/ui/toolbar/MainToolBarIndicators.qml +++ b/src/ui/toolbar/MainToolBarIndicators.qml @@ -49,14 +49,16 @@ Row { } function getMessageColor() { - if (activeVehicle.messageTypeNone) - return colorGrey - if (activeVehicle.messageTypeNormal) - return colorBlue; - if (activeVehicle.messageTypeWarning) - return colorOrange; - if (activeVehicle.messageTypeError) - return colorRed; + if (activeVehicle) { + if (activeVehicle.messageTypeNone) + return colorGrey + if (activeVehicle.messageTypeNormal) + return colorBlue; + if (activeVehicle.messageTypeWarning) + return colorOrange; + if (activeVehicle.messageTypeError) + return colorRed; + } // Cannot be so make make it obnoxious to show error console.log("Invalid vehicle message type") return "purple"; @@ -75,41 +77,30 @@ Row { } function getBatteryPercentageText() { - if(activeVehicle.batteryPercent > 98.9) { - return "100%" - } - if(activeVehicle.batteryPercent > 0.1) { - return activeVehicle.batteryPercent.toFixed(0) + "%" + if(activeVehicle) { + if(activeVehicle.batteryPercent > 98.9) { + return "100%" + } + if(activeVehicle.batteryPercent > 0.1) { + return activeVehicle.batteryPercent.toFixed(0) + "%" + } } return "N/A" } - function getBatteryColor() { - if(activeVehicle.batteryPercent > 75) { - return colorGreen - } - if(activeVehicle.batteryPercent > 50) { - return colorOrange - } - if(activeVehicle.batteryPercent > 0.1) { - return colorRed - } - return colorGrey - } - //------------------------------------------------------------------------- //-- Message Indicator Item { id: messages width: mainWindow.tbCellHeight height: mainWindow.tbCellHeight - visible: activeVehicle.messageCount + visible: activeVehicle ? activeVehicle.messageCount : false anchors.verticalCenter: parent.verticalCenter Item { id: criticalMessage anchors.fill: parent - visible: activeVehicle.messageCount > 0 && isMessageImportant + visible: activeVehicle ? (activeVehicle.messageCount > 0 && isMessageImportant) : false Image { source: "/qmlimages/Yield.svg" height: mainWindow.tbCellHeight * 0.75 @@ -160,7 +151,7 @@ Row { MouseArea { anchors.fill: parent onClicked: { - toolBar.showMessageArea() + mainWindow.showMessageArea() } } } @@ -182,20 +173,20 @@ Row { smooth: true width: mainWindow.tbCellHeight * 0.65 height: mainWindow.tbCellHeight * 0.5 - opacity: activeVehicle.satelliteCount < 1 ? 0.5 : 1 + opacity: activeVehicle ? (activeVehicle.satelliteCount < 1 ? 0.5 : 1) : 0.5 anchors.verticalCenter: parent.verticalCenter } SignalStrength { size: mainWindow.tbCellHeight * 0.5 - percent: getSatStrength(activeVehicle.satelliteCount) + percent: activeVehicle ? getSatStrength(activeVehicle.satelliteCount) : "" anchors.verticalCenter: parent.verticalCenter } } QGCLabel { - text: activeVehicle.satelliteCount + text: activeVehicle ? activeVehicle.satelliteCount : 0 font.pixelSize: tbFontSmall color: colorWhite - opacity: activeVehicle.satelliteCount < 1 ? 0.5 : 1 + opacity: activeVehicle ? (activeVehicle.satelliteCount < 1 ? 0.5 : 1) : 0.5 anchors.top: parent.top anchors.leftMargin: gpsIcon.width anchors.left: parent.left @@ -218,15 +209,22 @@ Row { smooth: true width: mainWindow.tbCellHeight * 0.65 height: mainWindow.tbCellHeight * 0.5 - opacity: activeVehicle.rcRSSI < 1 ? 0.5 : 1 + opacity: activeVehicle ? (activeVehicle.rcRSSI < 1 ? 0.5 : 1) : 0.5 anchors.verticalCenter: parent.verticalCenter } SignalStrength { size: mainWindow.tbCellHeight * 0.5 - percent: activeVehicle.rcRSSI + percent: activeVehicle ? activeVehicle.rcRSSI : 0 anchors.verticalCenter: parent.verticalCenter } } + MouseArea { + anchors.fill: parent + onClicked: { + var centerX = mapToItem(toolBar, x, y).x + (width / 2) + mainWindow.showPopUp(rcRSSIInfo, centerX) + } + } } //------------------------------------------------------------------------- @@ -235,47 +233,31 @@ Row { id: batteryStatus width: battRow.width * 1.1 height: mainWindow.tbCellHeight - opacity: (activeVehicle.batteryVoltage > 0) ? 1 : 0.5 + opacity: activeVehicle ? ((activeVehicle.batteryVoltage > 0) ? 1 : 0.5) : 0.5 Row { id: battRow height: mainWindow.tbCellHeight - spacing: tbSpacing anchors.horizontalCenter: parent.horizontalCenter - Column { - spacing: tbSpacing * 0.5 + Image { + source: "/qmlimages/Battery.svg" + fillMode: Image.PreserveAspectFit + mipmap: true + smooth: true + height: mainWindow.tbCellHeight * 0.65 anchors.verticalCenter: parent.verticalCenter - Image { - id: batIcon - source: "/qmlimages/Battery.svg" - fillMode: Image.PreserveAspectFit - mipmap: true - smooth: true - height: batPercent.height * 0.85 - anchors.horizontalCenter: parent.horizontalCenter - } - QGCLabel { - text: (activeVehicle.batteryConsumed > 0) ? activeVehicle.batteryConsumed.toFixed(0) + 'mAh' : 'N/A'; - font.pixelSize: tbFontSmall - color: getBatteryColor() - visible: QGroundControl.isAdvancedMode - anchors.horizontalCenter: parent.horizontalCenter - } } - Column { + QGCLabel { + text: getBatteryPercentageText() + font.pixelSize: tbFontLarge + color: getBatteryColor() anchors.verticalCenter: parent.verticalCenter - QGCLabel { - id: batPercent - text: getBatteryPercentageText() - font.pixelSize: tbFontLarge - color: getBatteryColor() - anchors.horizontalCenter: parent.horizontalCenter - } - QGCLabel { - text: getBatteryVoltageText() - font.pixelSize: tbFontNormal - color: getBatteryColor() - anchors.horizontalCenter: parent.horizontalCenter - } + } + } + MouseArea { + anchors.fill: parent + onClicked: { + var centerX = mapToItem(toolBar, x, y).x + (width / 2) + mainWindow.showPopUp(batteryInfo, centerX) } } } @@ -286,7 +268,7 @@ Row { id: vehicleSelectorButton width: ScreenTools.defaultFontPixelSize * 12 height: mainWindow.tbButtonWidth - text: "Vehicle " + activeVehicle.id + text: "Vehicle " + (activeVehicle ? activeVehicle.id : "None") visible: QGroundControl.multiVehicleManager.vehicles.count > 1 anchors.verticalCenter: parent.verticalCenter @@ -357,7 +339,7 @@ Row { anchors.verticalCenter: parent.verticalCenter } QGCLabel { - text: activeVehicle.flightMode + text: activeVehicle ? activeVehicle.flightMode : "N/A" font.pixelSize: tbFontLarge color: colorWhite anchors.verticalCenter: parent.verticalCenter @@ -373,8 +355,12 @@ Row { MenuItem { checkable: true - checked: activeVehicle.flightMode === text - onTriggered: activeVehicle.flightMode = text + checked: activeVehicle ? (activeVehicle.flightMode === text) : false + onTriggered: { + if(activeVehicle) { + activeVehicle.flightMode = text + } + } } } @@ -404,7 +390,7 @@ Row { } MouseArea { - visible: activeVehicle.flightModeSetAvailable + visible: activeVehicle ? activeVehicle.flightModeSetAvailable : false anchors.fill: parent onClicked: { flightModesMenu.popup() @@ -429,11 +415,11 @@ Row { fillMode: Image.PreserveAspectFit mipmap: true smooth: true - source: activeVehicle.armed ? "/qmlimages/Disarmed.svg" : "/qmlimages/Armed.svg" + source: activeVehicle ? (activeVehicle.armed ? "/qmlimages/Disarmed.svg" : "/qmlimages/Armed.svg") : "/qmlimages/Disarmed.svg" anchors.verticalCenter: parent.verticalCenter } QGCLabel { - text: activeVehicle.armed ? "Armed" : "Disarmed" + text: activeVehicle ? (activeVehicle.armed ? "Armed" : "Disarmed") : "" font.pixelSize: tbFontLarge color: colorWhite anchors.verticalCenter: parent.verticalCenter @@ -450,8 +436,8 @@ Row { visible: false icon: StandardIcon.Warning standardButtons: StandardButton.Yes | StandardButton.No - title: activeVehicle.armed ? "Disarming Vehicle" : "Arming Vehicle" - text: activeVehicle.armed ? "Do you want to disarm? This will cut power to all motors." : "Do you want to arm? This will enable all motors." + title: activeVehicle ? (activeVehicle.armed ? "Disarming Vehicle" : "Arming Vehicle") : "" + text: activeVehicle ? (activeVehicle.armed ? "Do you want to disarm? This will cut power to all motors." : "Do you want to arm? This will enable all motors.") : "" onYes: { activeVehicle.armed = !activeVehicle.armed armDialog.visible = false