Commit 0aea0088 authored by Don Gagne's avatar Don Gagne

Motor Setup/Testing support

parent 6920c117
......@@ -63,6 +63,7 @@
<file alias="LandModeCopter.svg">src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg</file>
<file alias="LowBattery.svg">src/AutoPilotPlugins/PX4/Images/LowBattery.svg</file>
<file alias="LowBatteryLight.svg">src/AutoPilotPlugins/PX4/Images/LowBatteryLight.svg</file>
<file alias="MotorComponentIcon.png">src/AutoPilotPlugins/Common/MotorComponentIcon.png</file>
<file alias="PowerComponentBattery_01cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_01cell.svg</file>
<file alias="PowerComponentBattery_02cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_02cell.svg</file>
<file alias="PowerComponentBattery_03cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_03cell.svg</file>
......
......@@ -638,6 +638,7 @@ HEADERS+= \
src/AutoPilotPlugins/APM/APMSensorsComponent.h \
src/AutoPilotPlugins/APM/APMSensorsComponentController.h \
src/AutoPilotPlugins/APM/APMTuningComponent.h \
src/AutoPilotPlugins/Common/MotorComponent.h \
src/AutoPilotPlugins/Common/RadioComponentController.h \
src/AutoPilotPlugins/Common/ESP8266ComponentController.h \
src/AutoPilotPlugins/Common/ESP8266Component.h \
......@@ -696,6 +697,7 @@ SOURCES += \
src/AutoPilotPlugins/APM/APMSensorsComponent.cc \
src/AutoPilotPlugins/APM/APMSensorsComponentController.cc \
src/AutoPilotPlugins/APM/APMTuningComponent.cc \
src/AutoPilotPlugins/Common/MotorComponent.cc \
src/AutoPilotPlugins/Common/RadioComponentController.cc \
src/AutoPilotPlugins/Common/ESP8266ComponentController.cc \
src/AutoPilotPlugins/Common/ESP8266Component.cc \
......
......@@ -39,6 +39,7 @@
<file alias="MainWindowNative.qml">src/ui/MainWindowNative.qml</file>
<file alias="MainWindowLeftPanel.qml">src/ui/MainWindowLeftPanel.qml</file>
<file alias="MissionEditor.qml">src/MissionEditor/MissionEditor.qml</file>
<file alias="MotorComponent.qml">src/AutoPilotPlugins/Common/MotorComponent.qml</file>
<file alias="PowerComponent.qml">src/AutoPilotPlugins/PX4/PowerComponent.qml</file>
<file alias="PowerComponentSummary.qml">src/AutoPilotPlugins/PX4/PowerComponentSummary.qml</file>
<file alias="PX4FlowSensor.qml">src/VehicleSetup/PX4FlowSensor.qml</file>
......@@ -55,6 +56,8 @@
<file alias="QGroundControl/Controls/MissionItemIndexLabel.qml">src/QmlControls/MissionItemIndexLabel.qml</file>
<file alias="QGroundControl/Controls/MissionItemStatus.qml">src/MissionEditor/MissionItemStatus.qml</file>
<file alias="QGroundControl/Controls/MissionCommandDialog.qml">src/QmlControls/MissionCommandDialog.qml</file>
<file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file>
<file alias="QGroundControl/Controls/MultiRotorMotorDisplayLegend.qml">src/QmlControls/MultiRotorMotorDisplayLegend.qml</file>
<file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file>
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
<file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file>
......@@ -71,6 +74,7 @@
<file alias="QGroundControl/Controls/QGCMovableItem.qml">src/QmlControls/QGCMovableItem.qml</file>
<file alias="QGroundControl/Controls/QGCPipable.qml">src/QmlControls/QGCPipable.qml</file>
<file alias="QGroundControl/Controls/QGCRadioButton.qml">src/QmlControls/QGCRadioButton.qml</file>
<file alias="QGroundControl/Controls/QGCSlider.qml">src/QmlControls/QGCSlider.qml</file>
<file alias="QGroundControl/Controls/QGCTextField.qml">src/QmlControls/QGCTextField.qml</file>
<file alias="QGroundControl/Controls/QGCToolBarButton.qml">src/QmlControls/QGCToolBarButton.qml</file>
<file alias="QGroundControl/Controls/QGCView.qml">src/QmlControls/QGCView.qml</file>
......@@ -78,6 +82,7 @@
<file alias="QGroundControl/Controls/QGCViewMessage.qml">src/QmlControls/QGCViewMessage.qml</file>
<file alias="QGroundControl/Controls/QGCViewPanel.qml">src/QmlControls/QGCViewPanel.qml</file>
<file alias="QGroundControl/Controls/RoundButton.qml">src/QmlControls/RoundButton.qml</file>
<file alias="QGroundControl/Controls/SetupPage.qml">src/AutoPilotPlugins/Common/SetupPage.qml</file>
<file alias="QGroundControl/Controls/SignalStrength.qml">src/ui/toolbar/SignalStrength.qml</file>
<file alias="QGroundControl/Controls/SliderSwitch.qml">src/QmlControls/SliderSwitch.qml</file>
<file alias="QGroundControl/Controls/SubMenuButton.qml">src/QmlControls/SubMenuButton.qml</file>
......@@ -113,7 +118,6 @@
<file alias="QGroundControl/FlightMap/QGCInstrumentWidget.qml">src/FlightMap/Widgets/QGCInstrumentWidget.qml</file>
<file alias="QGroundControl/FlightMap/QGCInstrumentWidgetAlternate.qml">src/FlightMap/Widgets/QGCInstrumentWidgetAlternate.qml</file>
<file alias="QGroundControl/FlightMap/QGCPitchIndicator.qml">src/FlightMap/Widgets/QGCPitchIndicator.qml</file>
<file alias="QGroundControl/FlightMap/QGCSlider.qml">src/FlightMap/Widgets/QGCSlider.qml</file>
<file alias="QGroundControl/FlightMap/QGCVideoBackground.qml">src/FlightMap/QGCVideoBackground.qml</file>
<file alias="QGroundControl/FlightMap/ValuesWidget.qml">src/FlightMap/Widgets/ValuesWidget.qml</file>
<file alias="QGroundControl/FlightMap/VibrationWidget.qml">src/FlightMap/Widgets/VibrationWidget.qml</file>
......
......@@ -25,6 +25,7 @@
#include "APMTuningComponent.h"
#include "APMSensorsComponent.h"
#include "APMPowerComponent.h"
#include "MotorComponent.h"
#include "APMCameraComponent.h"
#include "ESP8266Component.h"
......@@ -36,6 +37,7 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent)
, _cameraComponent(NULL)
, _flightModesComponent(NULL)
, _powerComponent(NULL)
, _motorComponent(NULL)
, _radioComponent(NULL)
, _safetyComponent(NULL)
, _sensorsComponent(NULL)
......@@ -77,6 +79,12 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void)
_powerComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_powerComponent));
if (_vehicle->multiRotor() || _vehicle->vtol()) {
_motorComponent = new MotorComponent(_vehicle, this);
_motorComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_motorComponent));
}
_safetyComponent = new APMSafetyComponent(_vehicle, this);
_safetyComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_safetyComponent));
......
......@@ -22,6 +22,7 @@ class APMTuningComponent;
class APMSafetyComponent;
class APMSensorsComponent;
class APMPowerComponent;
class MotorComponent;
class APMCameraComponent;
class ESP8266Component;
......@@ -41,6 +42,7 @@ public:
APMCameraComponent* cameraComponent (void) const { return _cameraComponent; }
APMFlightModesComponent* flightModesComponent(void) const { return _flightModesComponent; }
APMPowerComponent* powerComponent (void) const { return _powerComponent; }
MotorComponent* motorComponent (void) const { return _motorComponent; }
APMRadioComponent* radioComponent (void) const { return _radioComponent; }
APMSafetyComponent* safetyComponent (void) const { return _safetyComponent; }
APMSensorsComponent* sensorsComponent (void) const { return _sensorsComponent; }
......@@ -59,6 +61,7 @@ private:
APMCameraComponent* _cameraComponent;
APMFlightModesComponent* _flightModesComponent;
APMPowerComponent* _powerComponent;
MotorComponent* _motorComponent;
APMRadioComponent* _radioComponent;
APMSafetyComponent* _safetyComponent;
APMSensorsComponent* _sensorsComponent;
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "MotorComponent.h"
#include "APMAutoPilotPlugin.h"
#include "APMAirframeComponent.h"
MotorComponent::MotorComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) :
VehicleComponent(vehicle, autopilot, parent),
_name(tr("Motors"))
{
}
QString MotorComponent::name(void) const
{
return _name;
}
QString MotorComponent::description(void) const
{
return tr("Motors Setup is used to manually test motor control and direction.");
}
QString MotorComponent::iconResource(void) const
{
return QStringLiteral("/qmlimages/MotorComponentIcon.png");
}
bool MotorComponent::requiresSetup(void) const
{
return false;
}
bool MotorComponent::setupComplete(void) const
{
return true;
}
QStringList MotorComponent::setupCompleteChangedTriggerList(void) const
{
return QStringList();
}
QUrl MotorComponent::setupSource(void) const
{
return QUrl::fromUserInput(QStringLiteral("qrc:/qml/MotorComponent.qml"));
}
QUrl MotorComponent::summaryQmlSource(void) const
{
return QUrl();
}
QString MotorComponent::prerequisiteSetup(void) const
{
return QString();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#ifndef MotorComponent_H
#define MotorComponent_H
#include "VehicleComponent.h"
#include "Fact.h"
class MotorComponent : public VehicleComponent
{
Q_OBJECT
public:
MotorComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL);
// Virtuals from VehicleComponent
QStringList setupCompleteChangedTriggerList(void) const final;
// Virtuals from VehicleComponent
QString name(void) const final;
QString description(void) const final;
QString iconResource(void) const final;
bool requiresSetup(void) const final;
bool setupComplete(void) const final;
QUrl setupSource(void) const final;
QUrl summaryQmlSource(void) const final;
QString prerequisiteSetup(void) const final;
private:
const QString _name;
};
#endif
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.ScreenTools 1.0
SetupPage {
id: motorPage
pageComponent: pageComponent
readonly property int _barHeight: 10
readonly property int _barWidth: 5
readonly property int _sliderHeight: 10
FactPanelController {
id: controller
factPanel: motorPage.viewPanel
}
Component {
id: pageComponent
Column {
spacing: 10
Row {
id: motorSliders
enabled: safetySwitch.checked
spacing: ScreenTools.defaultFontPixelWidth * 4
Repeater {
id: sliderRepeater
model: controller.vehicle.motorCount == -1 ? 8 : controller.vehicle.motorCount
Column {
property alias motorSlider: slider
Timer {
interval: 250
running: true
repeat: true
property real _lastValue: 0
onTriggered: {
if (_lastValue != slider.value) {
controller.vehicle.motorTest(index + 1, slider.value, 1)
}
}
}
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
text: index + 1
}
QGCSlider {
id: slider
height: ScreenTools.defaultFontPixelHeight * _sliderHeight
orientation: Qt.Vertical
maximumValue: 100
value: 0
}
} // Column
} // Repeater
Column {
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("All")
}
QGCSlider {
id: allSlider
height: ScreenTools.defaultFontPixelHeight * _sliderHeight
orientation: Qt.Vertical
maximumValue: 100
value: 0
onValueChanged: {
for (var sliderIndex=0; sliderIndex<sliderRepeater.count; sliderIndex++) {
sliderRepeater.itemAt(sliderIndex).motorSlider.value = allSlider.value
}
}
}
} // Column
MultiRotorMotorDisplay {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
motorCount: controller.vehicle.motorCount
xConfig: controller.vehicle.xConfigMotors
coaxial: controller.vehicle.coaxialMotors
}
MultiRotorMotorDisplayLegend {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
}
} // Row
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("Moving the sliders will causes the motors to spin. Make sure you remove all props.")
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
Switch {
id: safetySwitch
onClicked: {
if (!checked) {
for (var sliderIndex=0; sliderIndex<sliderRepeater.count; sliderIndex++) {
sliderRepeater.itemAt(sliderIndex).motorSlider.value = 0
}
allSlider.value = 0
}
}
}
QGCLabel {
color: qgcPal.warningText
text: qsTr("Propellors are removed - Enable motor sliders")
}
} // Row
} // Column
} // Component
} // SetupPahe
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
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
/// Base view control for all Setup pages
QGCView {
id: setupView
viewPanel: setupPanel
property alias pageComponent: pageLoader.sourceComponent
property real _margins: ScreenTools.defaultFontPixelHeight / 2
QGCPalette { id: qgcPal; colorGroupEnabled: setupPanel.enabled }
QGCViewPanel {
id: setupPanel
anchors.fill: parent
QGCFlickable {
anchors.fill: parent
contentWidth: pageLoader.item.x + pageLoader.item.width
contentHeight: pageLoader.item.y + pageLoader.item.height
clip: true
Column {
id: headingColumn
anchors.left: parent.left
anchors.right: parent.right
spacing: _margins
QGCLabel {
font.pointSize: ScreenTools.largeFontPointSize
text: vehicleComponent.name + " " + qsTr("Setup")
visible: !ScreenTools.isShortScreen
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: vehicleComponent.description
visible: !ScreenTools.isShortScreen
}
}
Loader {
anchors.topMargin: _margins
anchors.top: headingColumn.bottom
id: pageLoader
}
}
}
}
......@@ -22,16 +22,17 @@
/// @brief This is the AutoPilotPlugin implementatin for the MAV_AUTOPILOT_PX4 type.
/// @author Don Gagne <don@thegagnes.com>
PX4AutoPilotPlugin::PX4AutoPilotPlugin(Vehicle* vehicle, QObject* parent) :
AutoPilotPlugin(vehicle, parent),
_airframeComponent(NULL),
_radioComponent(NULL),
_esp8266Component(NULL),
_flightModesComponent(NULL),
_sensorsComponent(NULL),
_safetyComponent(NULL),
_powerComponent(NULL),
_incorrectParameterVersion(false)
PX4AutoPilotPlugin::PX4AutoPilotPlugin(Vehicle* vehicle, QObject* parent)
: AutoPilotPlugin(vehicle, parent)
, _airframeComponent(NULL)
, _radioComponent(NULL)
, _esp8266Component(NULL)
, _flightModesComponent(NULL)
, _sensorsComponent(NULL)
, _safetyComponent(NULL)
, _powerComponent(NULL)
, _motorComponent(NULL)
, _incorrectParameterVersion(false)
{
Q_ASSERT(vehicle);
......@@ -74,6 +75,13 @@ const QVariantList& PX4AutoPilotPlugin::vehicleComponents(void)
_powerComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_powerComponent));
#if 0
// Coming soon
_motorComponent = new MotorComponent(_vehicle, this);
_motorComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_motorComponent));
#endif
_safetyComponent = new SafetyComponent(_vehicle, this);
_safetyComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_safetyComponent));
......
......@@ -21,6 +21,7 @@
#include "SafetyComponent.h"
#include "CameraComponent.h"
#include "PowerComponent.h"
#include "MotorComponent.h"
#include "PX4TuningComponent.h"
#include "Vehicle.h"
......@@ -50,6 +51,7 @@ public:
SafetyComponent* safetyComponent(void) { return _safetyComponent; }
CameraComponent* cameraComponent(void) { return _cameraComponent; }
PowerComponent* powerComponent(void) { return _powerComponent; }
MotorComponent* motorComponent(void) { return _motorComponent; }
PX4TuningComponent* tuningComponent(void) { return _tuningComponent; }
public slots:
......@@ -67,6 +69,7 @@ private:
SafetyComponent* _safetyComponent;
CameraComponent* _cameraComponent;
PowerComponent* _powerComponent;
MotorComponent* _motorComponent;
PX4TuningComponent* _tuningComponent;
bool _incorrectParameterVersion; ///< true: parameter version incorrect, setup not allowed
};
......
......@@ -122,7 +122,6 @@ APMCustomMode::APMCustomMode(uint32_t mode, bool settable) :
{
}
void APMCustomMode::setEnumToStringMapping(const QMap<uint32_t, QString>& enumToString)
{
_enumToString = enumToString;
......@@ -138,8 +137,10 @@ QString APMCustomMode::modeString() const
}
APMFirmwarePlugin::APMFirmwarePlugin(void)
: _coaxialMotors(false)
, _textSeverityAdjustmentNeeded(false)
{
_textSeverityAdjustmentNeeded = false;
}
bool APMFirmwarePlugin::isCapable(FirmwareCapabilities capabilities)
......@@ -380,6 +381,15 @@ bool APMFirmwarePlugin::_handleStatusText(Vehicle* vehicle, mavlink_message_t* m
// Start TCP video handshake with ARTOO
_soloVideoHandshake(vehicle);
} else if (messageText.contains(APM_FRAME_REXP)) {
// We need to parse the Frame: message in order to determine whether the motors are coaxial or not
QRegExp frameTypeRegex("^Frame: (\\S*)");
if (frameTypeRegex.indexIn(messageText) != -1) {
QString frameType = frameTypeRegex.cap(1);
if (!frameType.isEmpty() && (frameType == QStringLiteral("Y6") || frameType == QStringLiteral("OCTA_QUAD") || frameType == QStringLiteral("COAX"))) {
_coaxialMotors = true;
}
}
}
if (messageText.startsWith("PreArm")) {
......
......@@ -99,6 +99,8 @@ protected:
APMFirmwarePlugin(void);
void setSupportedModes(QList<APMCustomMode> supportedModes);
bool _coaxialMotors;
private slots:
void _artooSocketError(QAbstractSocket::SocketError socketError);
......
......@@ -197,3 +197,14 @@ void ArduCopterFirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode)
pauseVehicle(vehicle);
}
}
bool ArduCopterFirmwarePlugin::multiRotorCoaxialMotors(Vehicle* vehicle)
{
Q_UNUSED(vehicle);
return _coaxialMotors;
}
bool ArduCopterFirmwarePlugin::multiRotorXConfig(Vehicle* vehicle)
{
return vehicle->autopilotPlugin()->getParameterFact(FactSystem::defaultComponentId, "FRAME")->rawValue().toInt() != 0;
}
......@@ -64,6 +64,8 @@ public:
void guidedModeChangeAltitude(Vehicle* vehicle, double altitudeRel) final;
const FirmwarePlugin::remapParamNameMajorVersionMap_t& paramNameRemapMajorVersionMap(void) const final { return _remapParamName; }
virtual int remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const final;
virtual bool multiRotorCoaxialMotors(Vehicle* vehicle) final;
virtual bool multiRotorXConfig(Vehicle* vehicle) final;
private:
static bool _remapParamNameIntialized;
......
......@@ -181,6 +181,12 @@ public:
/// Returns the highest major version number that is known to the remap for this specified major version.
virtual int remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const;
/// @return true: Motors are coaxial like an X8 config, false: Quadcopter for example
virtual bool multiRotorCoaxialMotors(Vehicle* vehicle) { Q_UNUSED(vehicle); return false; }
/// @return true: X confiuration, false: Plus configuration
virtual bool multiRotorXConfig(Vehicle* vehicle) { Q_UNUSED(vehicle); return false; }
};
#endif
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.1
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
Item {
id: slider;
height: 12
property real value // value is read/write.
property real minimum: 0
property real maximum: 1
property int length: width - handle.width
Rectangle {
anchors.fill: parent
radius: ScreenTools.defaultFontPixelHeight * (0.5)
color: Qt.rgba(0,0,0,0.65);
}
Rectangle {
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelHeight * (0.33)
radius: ScreenTools.defaultFontPixelHeight * (0.33)
height: ScreenTools.defaultFontPixelHeight * (0.33)
width: handle.x - x
color: "#69bb17"
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: labelRect
width: label.width
height: label.height + ScreenTools.defaultFontPixelHeight * (0.33)
radius: ScreenTools.defaultFontPixelHeight * (0.33)
smooth: true
color: Qt.rgba(1,1,1,0.75);
border.width: ScreenTools.defaultFontPixelHeight * (0.083)
border.color: Qt.rgba(0,0,0,0.45);
anchors.bottom: handle.top
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33)
visible: mouseRegion.pressed
x: Math.max(Math.min(handle.x + (handle.width - width ) / 2, slider.width - width), 0)
QGCLabel{
id: label
color: "black"
text: slider.value.toFixed(2)
width: font.pointSize * 3.5
anchors.horizontalCenter: labelRect.horizontalCenter
horizontalAlignment: Text.AlignHCenter
anchors.verticalCenter: labelRect.verticalCenter
}
}
Rectangle {
id: handle;
smooth: true
width: ScreenTools.defaultFontPixelHeight * (2.16);
y: (slider.height - height) / 2;
x: (slider.value - slider.minimum) * slider.length / (slider.maximum - slider.minimum)
height: width
radius: width / 2
gradient: normalGradient
border.width: 2
border.color: "white"
Gradient {
id: normalGradient
GradientStop { position: 0.0; color: "#b0b0b0" }
GradientStop { position: 0.66; color: "#909090" }
GradientStop { position: 1.0; color: "#545454" }
}
MouseArea {
id: mouseRegion
hoverEnabled: false
anchors.fill: parent; drag.target: parent
drag.axis: Drag.XAxis; drag.minimumX: 0; drag.maximumX: slider.length
preventStealing: true
onPositionChanged: { slider.value = (slider.maximum - slider.minimum) * handle.x / slider.length + slider.minimum; }
}