You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
541 lines
20 KiB
541 lines
20 KiB
/*===================================================================== |
|
|
|
QGroundControl Open Source Ground Control Station |
|
|
|
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> |
|
|
|
This file is part of the QGROUNDCONTROL project |
|
|
|
QGROUNDCONTROL is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
QGROUNDCONTROL 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 General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
======================================================================*/ |
|
|
|
import QtQuick 2.5 |
|
import QtQuick.Controls 1.2 |
|
import QtQuick.Dialogs 1.2 |
|
|
|
import QGroundControl 1.0 |
|
import QGroundControl.FactSystem 1.0 |
|
import QGroundControl.FactControls 1.0 |
|
import QGroundControl.Palette 1.0 |
|
import QGroundControl.Controls 1.0 |
|
import QGroundControl.ScreenTools 1.0 |
|
import QGroundControl.Controllers 1.0 |
|
|
|
QGCView { |
|
id: qgcView |
|
viewPanel: panel |
|
|
|
QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } |
|
|
|
readonly property string dialogTitle: qsTr("Radio") |
|
readonly property real labelToMonitorMargin: defaultTextWidth * 3 |
|
|
|
property bool controllerCompleted: false |
|
property bool controllerAndViewReady: false |
|
|
|
function updateChannelCount() |
|
{ |
|
/* |
|
FIXME: Turned off for now, since it prevents binding. Need to restructure to |
|
allow binding and still check channel count |
|
if (controller.channelCount < controller.minChannelCount) { |
|
showDialog(channelCountDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, 0) |
|
} else { |
|
hideDialog() |
|
} |
|
*/ |
|
} |
|
|
|
RadioComponentController { |
|
id: controller |
|
factPanel: panel |
|
statusText: statusText |
|
cancelButton: cancelButton |
|
nextButton: nextButton |
|
skipButton: skipButton |
|
|
|
Component.onCompleted: { |
|
controllerCompleted = true |
|
if (qgcView.completedSignalled) { |
|
controllerAndViewReady = true |
|
controller.start() |
|
updateChannelCount() |
|
} |
|
} |
|
|
|
onChannelCountChanged: updateChannelCount() |
|
onFunctionMappingChangedAPMReboot: showMessage(qsTr("Reboot required"), qsTr("Your stick mappings have changed, you must reboot the vehicle for correct operation."), StandardButton.Ok) |
|
} |
|
|
|
onCompleted: { |
|
if (controllerCompleted) { |
|
controllerAndViewReady = true |
|
controller.start() |
|
updateChannelCount() |
|
} |
|
} |
|
|
|
QGCViewPanel { |
|
id: panel |
|
anchors.fill: parent |
|
|
|
Component { |
|
id: copyTrimsDialogComponent |
|
|
|
QGCViewMessage { |
|
message: qsTr("Center your sticks and move throttle all the way down, then press Ok to copy trims. After pressing Ok, reset the trims on your radio back to zero.") |
|
|
|
function accept() { |
|
hideDialog() |
|
controller.copyTrims() |
|
} |
|
} |
|
} |
|
|
|
Component { |
|
id: zeroTrimsDialogComponent |
|
|
|
QGCViewMessage { |
|
message: qsTr("Before calibrating you should zero all your trims and subtrims. Click Ok to start Calibration.\n\n%1").arg( |
|
(QGroundControl.multiVehicleManager.activeVehicle.px4Firmware ? "" : qsTr("Please ensure all motor power is disconnected AND all props are removed from the vehicle."))) |
|
|
|
function accept() { |
|
hideDialog() |
|
controller.nextButtonClicked() |
|
} |
|
} |
|
} |
|
|
|
Component { |
|
id: channelCountDialogComponent |
|
|
|
QGCViewMessage { |
|
message: controller.channelCount == 0 ? qsTr("Please turn on transmitter.") : qsTr("%1 channels or more are needed to fly.").arg(controller.minChannelCount) |
|
} |
|
} |
|
|
|
Component { |
|
id: spektrumBindDialogComponent |
|
|
|
QGCViewDialog { |
|
|
|
function accept() { |
|
controller.spektrumBindMode(radioGroup.current.bindMode) |
|
hideDialog() |
|
} |
|
|
|
function reject() { |
|
hideDialog() |
|
} |
|
|
|
Column { |
|
anchors.fill: parent |
|
spacing: 5 |
|
|
|
QGCLabel { |
|
width: parent.width |
|
wrapMode: Text.WordWrap |
|
text: qsTr("Click Ok to place your Spektrum receiver in the bind mode. Select the specific receiver type below:") |
|
} |
|
|
|
ExclusiveGroup { id: radioGroup } |
|
|
|
QGCRadioButton { |
|
exclusiveGroup: radioGroup |
|
text: qsTr("DSM2 Mode") |
|
|
|
property int bindMode: RadioComponentController.DSM2 |
|
} |
|
|
|
QGCRadioButton { |
|
exclusiveGroup: radioGroup |
|
text: qsTr("DSMX (7 channels or less)") |
|
|
|
property int bindMode: RadioComponentController.DSMX7 |
|
} |
|
|
|
QGCRadioButton { |
|
exclusiveGroup: radioGroup |
|
checked: true |
|
text: qsTr("DSMX (8 channels or more)") |
|
|
|
property int bindMode: RadioComponentController.DSMX8 |
|
} |
|
} |
|
} |
|
} // Component - spektrumBindDialogComponent |
|
|
|
// Live channel monitor control component |
|
Component { |
|
id: channelMonitorDisplayComponent |
|
|
|
Item { |
|
property int rcValue: 1500 |
|
|
|
|
|
property int __lastRcValue: 1500 |
|
readonly property int __rcValueMaxJitter: 2 |
|
property color __barColor: qgcPal.windowShade |
|
|
|
// Bar |
|
Rectangle { |
|
id: bar |
|
anchors.verticalCenter: parent.verticalCenter |
|
width: parent.width |
|
height: parent.height / 2 |
|
color: __barColor |
|
} |
|
|
|
// Center point |
|
Rectangle { |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
width: defaultTextWidth / 2 |
|
height: parent.height |
|
color: qgcPal.window |
|
} |
|
|
|
// Indicator |
|
Rectangle { |
|
anchors.verticalCenter: parent.verticalCenter |
|
width: parent.height * 0.75 |
|
height: width |
|
x: ((Math.abs((rcValue - 1000) - (reversed ? 1000 : 0)) / 1000) * parent.width) - (width / 2) |
|
radius: width / 2 |
|
color: qgcPal.text |
|
visible: mapped |
|
} |
|
|
|
QGCLabel { |
|
anchors.fill: parent |
|
horizontalAlignment: Text.AlignHCenter |
|
verticalAlignment: Text.AlignVCenter |
|
text: qsTr("Not Mapped") |
|
visible: !mapped |
|
} |
|
|
|
ColorAnimation { |
|
id: barAnimation |
|
target: bar |
|
property: "color" |
|
from: "yellow" |
|
to: __barColor |
|
duration: 1500 |
|
} |
|
|
|
/* |
|
// FIXME: Bar animation is turned off for now to figure out better usbaility |
|
onRcValueChanged: { |
|
if (Math.abs(rcValue - __lastRcValue) > __rcValueMaxJitter) { |
|
__lastRcValue = rcValue |
|
barAnimation.restart() |
|
} |
|
} |
|
|
|
// rcValue debugger |
|
QGCLabel { |
|
anchors.fill: parent |
|
text: rcValue |
|
} |
|
*/ |
|
} |
|
} // Component - channelMonitorDisplayComponent |
|
|
|
// Main view Qml starts here |
|
|
|
QGCFlickable { |
|
anchors.fill: parent |
|
contentHeight: Math.max(leftColumn.height, rightColumn.height) |
|
clip: true |
|
|
|
// Left side column |
|
Column { |
|
id: leftColumn |
|
anchors.left: parent.left |
|
anchors.right: columnSpacer.left |
|
spacing: 10 |
|
|
|
// Attitude Controls |
|
Column { |
|
width: parent.width |
|
spacing: 5 |
|
QGCLabel { text: qsTr("Attitude Controls") } |
|
|
|
Item { |
|
width: parent.width |
|
height: defaultTextHeight * 2 |
|
QGCLabel { |
|
id: rollLabel |
|
width: defaultTextWidth * 10 |
|
text: qsTr("Roll") |
|
} |
|
|
|
Loader { |
|
id: rollLoader |
|
anchors.left: rollLabel.right |
|
anchors.right: parent.right |
|
height: qgcView.defaultTextHeight |
|
width: 100 |
|
sourceComponent: channelMonitorDisplayComponent |
|
|
|
property real defaultTextWidth: qgcView.defaultTextWidth |
|
property bool mapped: controller.rollChannelMapped |
|
property bool reversed: controller.rollChannelReversed |
|
} |
|
|
|
Connections { |
|
target: controller |
|
|
|
onRollChannelRCValueChanged: rollLoader.item.rcValue = rcValue |
|
} |
|
} |
|
|
|
Item { |
|
width: parent.width |
|
height: defaultTextHeight * 2 |
|
|
|
QGCLabel { |
|
id: pitchLabel |
|
width: defaultTextWidth * 10 |
|
text: qsTr("Pitch") |
|
} |
|
|
|
Loader { |
|
id: pitchLoader |
|
anchors.left: pitchLabel.right |
|
anchors.right: parent.right |
|
height: qgcView.defaultTextHeight |
|
width: 100 |
|
sourceComponent: channelMonitorDisplayComponent |
|
|
|
property real defaultTextWidth: qgcView.defaultTextWidth |
|
property bool mapped: controller.pitchChannelMapped |
|
property bool reversed: controller.pitchChannelReversed |
|
} |
|
|
|
Connections { |
|
target: controller |
|
|
|
onPitchChannelRCValueChanged: pitchLoader.item.rcValue = rcValue |
|
} |
|
} |
|
|
|
Item { |
|
width: parent.width |
|
height: defaultTextHeight * 2 |
|
|
|
QGCLabel { |
|
id: yawLabel |
|
width: defaultTextWidth * 10 |
|
text: qsTr("Yaw") |
|
} |
|
|
|
Loader { |
|
id: yawLoader |
|
anchors.left: yawLabel.right |
|
anchors.right: parent.right |
|
height: qgcView.defaultTextHeight |
|
width: 100 |
|
sourceComponent: channelMonitorDisplayComponent |
|
|
|
property real defaultTextWidth: qgcView.defaultTextWidth |
|
property bool mapped: controller.yawChannelMapped |
|
property bool reversed: controller.yawChannelReversed |
|
} |
|
|
|
Connections { |
|
target: controller |
|
|
|
onYawChannelRCValueChanged: yawLoader.item.rcValue = rcValue |
|
} |
|
} |
|
|
|
Item { |
|
width: parent.width |
|
height: defaultTextHeight * 2 |
|
|
|
QGCLabel { |
|
id: throttleLabel |
|
width: defaultTextWidth * 10 |
|
text: qsTr("Throttle") |
|
} |
|
|
|
Loader { |
|
id: throttleLoader |
|
anchors.left: throttleLabel.right |
|
anchors.right: parent.right |
|
height: qgcView.defaultTextHeight |
|
width: 100 |
|
sourceComponent: channelMonitorDisplayComponent |
|
|
|
property real defaultTextWidth: qgcView.defaultTextWidth |
|
property bool mapped: controller.throttleChannelMapped |
|
property bool reversed: controller.throttleChannelReversed |
|
} |
|
|
|
Connections { |
|
target: controller |
|
|
|
onThrottleChannelRCValueChanged: throttleLoader.item.rcValue = rcValue |
|
} |
|
} |
|
} // Column - Attitude Control labels |
|
|
|
// Command Buttons |
|
Row { |
|
spacing: 10 |
|
|
|
QGCButton { |
|
id: skipButton |
|
text: qsTr("Skip") |
|
|
|
onClicked: controller.skipButtonClicked() |
|
} |
|
|
|
QGCButton { |
|
id: cancelButton |
|
text: qsTr("Cancel") |
|
|
|
onClicked: controller.cancelButtonClicked() |
|
} |
|
|
|
QGCButton { |
|
id: nextButton |
|
primary: true |
|
text: qsTr("Calibrate") |
|
|
|
onClicked: { |
|
if (text == qsTr("Calibrate")) { |
|
showDialog(zeroTrimsDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel) |
|
} else { |
|
controller.nextButtonClicked() |
|
} |
|
} |
|
} |
|
} // Row - Buttons |
|
|
|
// Status Text |
|
QGCLabel { |
|
id: statusText |
|
width: parent.width |
|
wrapMode: Text.WordWrap |
|
} |
|
|
|
Item { |
|
width: 10 |
|
height: defaultTextHeight * 4 |
|
} |
|
|
|
Rectangle { |
|
width: parent.width |
|
height: 1 |
|
border.color: qgcPal.text |
|
border.width: 1 |
|
} |
|
|
|
QGCLabel { text: qsTr("Additional Radio setup:") } |
|
|
|
Row { |
|
spacing: 10 |
|
|
|
QGCLabel { |
|
anchors.baseline: bindButton.baseline |
|
text: qsTr("Place Spektrum satellite receiver in bind mode:") |
|
} |
|
|
|
QGCButton { |
|
id: bindButton |
|
text: qsTr("Spektrum Bind") |
|
|
|
onClicked: showDialog(spektrumBindDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel) |
|
} |
|
} |
|
|
|
QGCButton { |
|
text: qsTr("Copy Trims") |
|
visible: QGroundControl.multiVehicleManager.activeVehicle.px4Firmware |
|
onClicked: showDialog(copyTrimsDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel) |
|
} |
|
|
|
Repeater { |
|
model: QGroundControl.multiVehicleManager.activeVehicle.px4Firmware ? [ "RC_MAP_FLAPS", "RC_MAP_AUX1", "RC_MAP_AUX2", "RC_MAP_AUX3" ] : 0 |
|
|
|
Row { |
|
spacing: ScreenTools.defaultFontPixelWidth |
|
property Fact fact: controller.getParameterFact(-1, modelData) |
|
|
|
QGCLabel { |
|
anchors.baseline: optCombo.baseline |
|
text: fact.shortDescription + ":" |
|
} |
|
|
|
FactComboBox { |
|
id: optCombo |
|
width: ScreenTools.defaultFontPixelWidth * 15 |
|
fact: parent.fact |
|
indexModel: false |
|
} |
|
} |
|
} // Repeater |
|
} // Column - Left Column |
|
|
|
Item { |
|
id: columnSpacer |
|
anchors.right: rightColumn.left |
|
width: 20 |
|
} |
|
|
|
// Right side column |
|
Column { |
|
id: rightColumn |
|
anchors.top: parent.top |
|
anchors.right: parent.right |
|
width: defaultTextWidth * 35 |
|
spacing: 10 |
|
|
|
Row { |
|
spacing: 10 |
|
ExclusiveGroup { id: modeGroup } |
|
QGCRadioButton { |
|
exclusiveGroup: modeGroup |
|
text: qsTr("Mode 1") |
|
checked: controller.transmitterMode == 1 |
|
|
|
onClicked: controller.transmitterMode = 1 |
|
} |
|
|
|
QGCRadioButton { |
|
exclusiveGroup: modeGroup |
|
text: qsTr("Mode 2") |
|
checked: controller.transmitterMode == 2 |
|
|
|
onClicked: controller.transmitterMode = 2 |
|
} |
|
} |
|
|
|
Image { |
|
width: parent.width |
|
height: defaultTextHeight * 15 |
|
fillMode: Image.PreserveAspectFit |
|
smooth: true |
|
source: controller.imageHelp |
|
} |
|
|
|
RCChannelMonitor { |
|
width: parent.width |
|
} |
|
} // Column - Right Column |
|
} // QGCFlickable |
|
} // QGCViewPanel |
|
}
|
|
|