diff --git a/qgcresources.qrc b/qgcresources.qrc index 1adcca7a6f3c8f61ad2f9c6182230a324745696b..25e0e8baa1608979a8cf2025ba56125edbd19d3b 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -193,6 +193,10 @@ resources/takeoff.svg resources/TrashDelete.svg resources/waves.svg + resources/wind-guru.svg + resources/wind-rose.svg + resources/wind-roseBlack.svg + resources/wind-rose-arrow.svg resources/XDelete.svg resources/XDeleteBlack.svg resources/icons/qgroundcontrol.ico diff --git a/resources/wind-guru.svg b/resources/wind-guru.svg new file mode 100644 index 0000000000000000000000000000000000000000..f232bff5ac1297c8e06e178f53385bfe4ef85c1d --- /dev/null +++ b/resources/wind-guru.svg @@ -0,0 +1,35 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/resources/wind-rose-arrow.svg b/resources/wind-rose-arrow.svg new file mode 100644 index 0000000000000000000000000000000000000000..94830efecccf4810874884e3c2a89c64743ce6d5 --- /dev/null +++ b/resources/wind-rose-arrow.svg @@ -0,0 +1,62 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/resources/wind-rose.svg b/resources/wind-rose.svg new file mode 100644 index 0000000000000000000000000000000000000000..c00875821c959d17f973bc3f5292e72d19916fa9 --- /dev/null +++ b/resources/wind-rose.svg @@ -0,0 +1,59 @@ + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/resources/wind-roseBlack.svg b/resources/wind-roseBlack.svg new file mode 100644 index 0000000000000000000000000000000000000000..7d13f530efb8d193a05a203ca8d6c070849bb669 --- /dev/null +++ b/resources/wind-roseBlack.svg @@ -0,0 +1,59 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/src/PlanView/SurveyItemEditor.qml b/src/PlanView/SurveyItemEditor.qml index 7415c6c583b42397c3d35e13dfea8961c48b659a..2fa223edce9f8b151913722be33c27131c318b59 100644 --- a/src/PlanView/SurveyItemEditor.qml +++ b/src/PlanView/SurveyItemEditor.qml @@ -1,6 +1,8 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.2 +import QtQuick.Extras 1.4 import QtQuick.Layouts 1.2 import QGroundControl 1.0 @@ -398,10 +400,40 @@ Rectangle { columns: 2 visible: gridHeader.checked - QGCLabel { text: qsTr("Angle") } + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + columnSpacing: _margin + rowSpacing: _margin + columns: 3 + visible: gridHeader.checked + + QGCLabel { + id: angleText + text: qsTr("Angle") + } + + Item { Layout.fillWidth: true } + + property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + ToolButton { + id: windRoseButton + anchors.verticalCenter: angleText.verticalCenter + iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg" + visible: _activeVehicle ? _activeVehicle.fixedWing : true + + onClicked: { + var cords = windRoseButton.mapToItem(_root, 0, 0) + windRosePie.popup(cords.x + windRoseButton.width / 2, cords.y + windRoseButton.height / 2); + } + } + } + FactTextField { + id: gridAngleText fact: missionItem.gridAngle Layout.fillWidth: true + Layout.columnSpan: 1 } QGCLabel { text: qsTr("Turnaround dist") } @@ -467,13 +499,49 @@ Rectangle { spacing: _margin visible: manualGridHeader.visible && manualGridHeader.checked + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + columnSpacing: _margin + rowSpacing: _margin + columns: 4 + visible: gridHeader.checked + + QGCLabel { + id: manualAngleText + text: qsTr("Angle") + Layout.columnSpan: 1 + Layout.fillWidth: true + } + + property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + ToolButton { + id: manualWindRoseButton + anchors.verticalCenter: manualAngleText.verticalCenter + Layout.columnSpan: 1 + iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg" + visible: _activeVehicle ? _activeVehicle.fixedWing : true + + onClicked: { + var cords = manualWindRoseButton.mapToItem(_root, 0, 0) + windRosePie.popup(cords.x + manualWindRoseButton.width / 2, cords.y + manualWindRoseButton.height / 2); + } + } + + FactTextField { + id: manualGridAngleText + fact: missionItem.gridAngle + Layout.columnSpan: 2 + } + } + FactTextFieldGrid { anchors.left: parent.left anchors.right: parent.right columnSpacing: ScreenTools.defaultFontPixelWidth rowSpacing: _margin - factList: [ missionItem.gridAngle, missionItem.gridSpacing, missionItem.gridAltitude, missionItem.turnaroundDist ] - factLabels: [ qsTr("Angle"), qsTr("Spacing"), qsTr("Altitude"), qsTr("Turnaround dist")] + factList: [ missionItem.gridSpacing, missionItem.gridAltitude, missionItem.turnaroundDist ] + factLabels: [ qsTr("Spacing"), qsTr("Altitude"), qsTr("Turnaround dist")] } QGCCheckBox { @@ -516,4 +584,112 @@ Rectangle { } } } + + QGCColoredImage { + id: windRoseArrow + source: "/res/wind-rose-arrow.svg" + visible: windRosePie.visible + width: windRosePie.width / 5 + height: width * 1.454 + smooth: true + color: qgcPal.colorGrey + transform: Rotation { + origin.x: windRoseArrow.width / 2 + origin.y: windRoseArrow.height / 2 + axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle + } + x: windRosePie.x + Math.sin(- windRosePie.angle*Math.PI/180 - Math.PI/2)*(windRosePie.width/2 - windRoseArrow.width/2) + windRosePie.width / 2 - windRoseArrow.width / 2 + y: windRosePie.y + Math.cos(- windRosePie.angle*Math.PI/180 - Math.PI/2)*(windRosePie.width/2 - windRoseArrow.width/2) + windRosePie.height / 2 - windRoseArrow.height / 2 + z: windRosePie.z + 1 + } + + QGCColoredImage { + id: windGuru + source: "/res/wind-guru.svg" + visible: windRosePie.visible + width: windRosePie.width / 3 + height: width * 4.28e-1 + smooth: true + color: qgcPal.colorGrey + transform: Rotation { + origin.x: windGuru.width / 2 + origin.y: windGuru.height / 2 + axis { x: 0; y: 0; z: 1 } angle: windRosePie.angle + 180 + } + x: windRosePie.x + Math.sin(- windRosePie.angle*Math.PI/180 - 3*Math.PI/2)*(windRosePie.width/2) + windRosePie.width / 2 - windGuru.width / 2 + y: windRosePie.y + Math.cos(- windRosePie.angle*Math.PI/180 - 3*Math.PI/2)*(windRosePie.height/2) + windRosePie.height / 2 - windGuru.height / 2 + z: windRosePie.z + 1 + } + + Item { + id: windRosePie + height: 2.6*windRoseButton.height + width: 2.6*windRoseButton.width + visible: false + focus: true + + property string colorCircle: qgcPal.windowShade + property string colorBackground: qgcPal.colorGrey + property real lineWidth: windRoseButton.width / 3 + property real angle: 0 + + Canvas { + id: windRoseCanvas + anchors.fill: parent + + onPaint: { + var ctx = getContext("2d") + var x = width / 2 + var y = height / 2 + var angleWidth = 0.03 * Math.PI + var start = windRosePie.angle*Math.PI/180 - angleWidth + var end = windRosePie.angle*Math.PI/180 + angleWidth + ctx.reset() + + ctx.beginPath(); + ctx.arc(x, y, (width / 3) - windRosePie.lineWidth / 2, 0, 2*Math.PI, false) + ctx.lineWidth = windRosePie.lineWidth + ctx.strokeStyle = windRosePie.colorBackground + ctx.stroke() + + ctx.beginPath(); + ctx.arc(x, y, (width / 3) - windRosePie.lineWidth / 2, start, end, false) + ctx.lineWidth = windRosePie.lineWidth + ctx.strokeStyle = windRosePie.colorCircle + ctx.stroke() + } + } + + onFocusChanged: { + visible = focus + } + + function popup(x, y) { + if (x !== undefined) + windRosePie.x = x - windRosePie.width / 2; + if (y !== undefined) + windRosePie.y = y - windRosePie.height / 2; + + windRosePie.visible = true; + windRosePie.focus = true + } + + MouseArea { + id: mouseArea + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onClicked: { + windRosePie.visible = false; + } + onPositionChanged: { + var point = Qt.point(mouseX - parent.width / 2, mouseY - parent.height / 2) + var angle = Math.round(Math.atan2(point.y, point.x) * 180 / Math.PI) + windRoseCanvas.requestPaint() + windRosePie.angle = angle + gridAngleText.text = angle + gridAngleText.editingFinished(); + } + } + } }