diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index e611bc24437b9990df83b279040248dead77d67d..ccabc9be31c3c8ebd738baa43a49810da4170be0 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -32,6 +32,8 @@
src/QmlControls/VehicleSummaryRow.qml
src/QmlControls/arrow-down.png
src/ViewWidgets/ViewWidget.qml
+ src/QmlControls/ViewWithDialog.qml
+
src/QmlControls/ParameterEditor.qml
src/ViewWidgets/ParameterEditorWidget.qml
diff --git a/src/AutoPilotPlugins/PX4/AirframeComponent.qml b/src/AutoPilotPlugins/PX4/AirframeComponent.qml
index b7a483768cb5fddbde800432d810d2127cc4fdcc..37a58d2f3d72328f61d26c0d956965a2126e1e0d 100644
--- a/src/AutoPilotPlugins/PX4/AirframeComponent.qml
+++ b/src/AutoPilotPlugins/PX4/AirframeComponent.qml
@@ -24,6 +24,7 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
+import QtQuick.Dialogs 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
@@ -31,132 +32,190 @@ import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Controllers 1.0
-FactPanel {
- id: panel
+ViewWithDialog {
+ viewComponent: view
- AirframeComponentController { id: controller; factPanel: panel }
+ Component {
+ id: view
- Rectangle {
- anchors.fill: parent
+ FactPanel {
+ id: panel
+ anchors.fill: parent
- QGCPalette { id: qgcPal; colorGroupEnabled: true }
+ signal showDialog(Component component, string title, int charWidth, int buttons)
+ signal hideDialog
- color: qgcPal.window
+ function doWorkAfterComponentCompleted() {
+ if (controller.showCustomConfigPanel) {
+ panel.showDialog(customConfigDialog, "Custom Airframe Config", 50, StandardButton.Reset)
+ }
+ }
- Column {
- anchors.fill: parent
+ AirframeComponentController {
+ id: controller
+ factPanel: panel
+ }
- QGCLabel {
- text: "AIRFRAME CONFIG"
- font.pointSize: 20
+ Component {
+ id: customConfigDialog
+
+ QGCLabel {
+ id: customConfigPanel
+ anchors.fill: parent
+ wrapMode: Text.WordWrap
+ text: "Your vehicle is using a custom airframe configuration. " +
+ "This configuration can only be modified through the Parameter Editor.\n\n" +
+ "If you want to Reset your airframe configuration and select a standard configuration, click 'Reset' above."
+
+ signal hideDialog
+
+ Fact { id: sys_autostart; name: "SYS_AUTOSTART" }
+
+ function accept() {
+ sys_autostart.value = 0
+ customConfigPanel.hideDialog()
+ }
+ }
}
- Item { height: 20; width: 10 } // spacer
+ Rectangle {
+ anchors.fill: parent
+
+ QGCPalette { id: qgcPal; colorGroupEnabled: true }
+
+ color: qgcPal.window
+
+ QGCLabel {
+ id: header
+ width: parent.width
+ font.pointSize: 20
+ text: "AIRFRAME CONFIG"
+ }
- Row {
- width: parent.width
+ Item {
+ id: headingSpacer
+ anchors.top: header.bottom
+ height: 20
+ width: 20
+ }
QGCLabel {
- width: parent.width - applyButton.width
- text: "Select you airframe type and specific vehicle bellow. Click 'Apply and Restart' when ready and your vehicle will be disconnected, rebooted to the new settings and re-connected."
- wrapMode: Text.WordWrap
+ anchors.top: headingSpacer.bottom
+ width: parent.width - applyButton.width - 5
+ text: "Select you airframe type and specific vehicle bellow. Click 'Apply and Restart' when ready and your vehicle will be disconnected, rebooted to the new settings and re-connected."
+ wrapMode: Text.WordWrap
}
QGCButton {
- id: applyButton
- text: "Apply and Restart"
+ id: applyButton
+ anchors.top: headingSpacer.bottom
+ anchors.right: parent.right
+ text: "Apply and Restart"
+
onClicked: { controller.changeAutostart() }
}
- }
- Item { height: 20; width: 10 } // spacer
+ Item {
+ id: lastSpacer
+ anchors.top: applyButton.bottom
+ height: 20
+ width: 10
+ }
- Flow {
- width: parent.width
- spacing: 10
+ ScrollView {
+ id: scroll
+ anchors.top: lastSpacer.bottom
+ anchors.bottom: parent.bottom
+ width: parent.width
+ horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
- ExclusiveGroup {
- id: airframeTypeExclusive
- }
+ Flow {
+ width: scroll.width
+ spacing: 10
- Repeater {
- model: controller.airframeTypes
+ ExclusiveGroup {
+ id: airframeTypeExclusive
+ }
- // Outer summary item rectangle
- Rectangle {
- readonly property real titleHeight: 30
- readonly property real innerMargin: 10
+ Repeater {
+ model: controller.airframeTypes
- width: 250
- height: 200
- color: qgcPal.windowShade
+ // Outer summary item rectangle
+ Rectangle {
+ readonly property real titleHeight: 30
+ readonly property real innerMargin: 10
- Rectangle {
- id: title
- width: parent.width
- height: parent.titleHeight
- color: qgcPal.windowShadeDark
+ width: 250
+ height: 200
+ color: qgcPal.windowShade
- Text {
- anchors.fill: parent
+ Rectangle {
+ id: title
+ width: parent.width
+ height: parent.titleHeight
+ color: qgcPal.windowShadeDark
- color: qgcPal.buttonText
- font.pixelSize: 12
- text: modelData.name
+ Text {
+ anchors.fill: parent
- verticalAlignment: TextEdit.AlignVCenter
- horizontalAlignment: TextEdit.AlignHCenter
- }
- }
+ color: qgcPal.buttonText
+ font.pixelSize: 12
+ text: modelData.name
- Image {
- id: image
- x: innerMargin
- width: parent.width - (innerMargin * 2)
- height: parent.height - title.height - combo.height - (innerMargin * 3)
- anchors.topMargin: innerMargin
- anchors.top: title.bottom
+ verticalAlignment: TextEdit.AlignVCenter
+ horizontalAlignment: TextEdit.AlignHCenter
+ }
+ }
- source: modelData.imageResource
- fillMode: Image.PreserveAspectFit
- smooth: true
+ Image {
+ id: image
+ x: innerMargin
+ width: parent.width - (innerMargin * 2)
+ height: parent.height - title.height - combo.height - (innerMargin * 3)
+ anchors.topMargin: innerMargin
+ anchors.top: title.bottom
- }
+ source: modelData.imageResource
+ fillMode: Image.PreserveAspectFit
+ smooth: true
- QGCCheckBox {
- id: airframeCheckBox
- anchors.bottom: image.bottom
- anchors.right: image.right
- checked: modelData.name == controller.currentAirframeType
- exclusiveGroup: airframeTypeExclusive
+ }
- onCheckedChanged: {
- if (checked && combo.currentIndex != -1) {
- controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
+ QGCCheckBox {
+ id: airframeCheckBox
+ anchors.bottom: image.bottom
+ anchors.right: image.right
+ checked: modelData.name == controller.currentAirframeType
+ exclusiveGroup: airframeTypeExclusive
+
+ onCheckedChanged: {
+ if (checked && combo.currentIndex != -1) {
+ controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
+ }
+ }
}
- }
- }
- QGCComboBox {
- id: combo
- objectName: modelData.airframeType + "ComboBox"
- x: innerMargin
- anchors.topMargin: innerMargin
- anchors.top: image.bottom
- width: parent.width - (innerMargin * 2)
- model: modelData.airframes
- currentIndex: (modelData.name == controller.currentAirframeType) ? controller.currentVehicleIndex : 0
-
- onCurrentIndexChanged: {
- if (airframeCheckBox.checked) {
- controller.autostartId = modelData.airframes[currentIndex].autostartId
+ QGCComboBox {
+ id: combo
+ objectName: modelData.airframeType + "ComboBox"
+ x: innerMargin
+ anchors.topMargin: innerMargin
+ anchors.top: image.bottom
+ width: parent.width - (innerMargin * 2)
+ model: modelData.airframes
+ currentIndex: (modelData.name == controller.currentAirframeType) ? controller.currentVehicleIndex : 0
+
+ onCurrentIndexChanged: {
+ if (airframeCheckBox.checked) {
+ controller.autostartId = modelData.airframes[currentIndex].autostartId
+ }
+ }
}
}
- }
- }
- }
- }
-
- }
- }
+ } // Repeater - summary boxes
+ } // Flow - summary boxes
+ } // Scroll View - summary boxes
+ } // Rectangle - background
+ } // FactPanel
+ } // Component - View
}
\ No newline at end of file
diff --git a/src/AutoPilotPlugins/PX4/AirframeComponentController.cc b/src/AutoPilotPlugins/PX4/AirframeComponentController.cc
index d0c9bf04ece1c34ab82147523d22b140fd623f1d..2cc1386f495f8e507e68f9e59310695ae2c91bd0 100644
--- a/src/AutoPilotPlugins/PX4/AirframeComponentController.cc
+++ b/src/AutoPilotPlugins/PX4/AirframeComponentController.cc
@@ -40,7 +40,8 @@ bool AirframeComponentController::_typesRegistered = false;
AirframeComponentController::AirframeComponentController(void) :
_uas(NULL),
_currentVehicleIndex(0),
- _autostartId(0)
+ _autostartId(0),
+ _showCustomConfigPanel(false)
{
_uas = UASManager::instance()->getActiveUAS();
Q_ASSERT(_uas);
@@ -82,10 +83,9 @@ AirframeComponentController::AirframeComponentController(void) :
_airframeTypes.append(QVariant::fromValue(airframeType));
}
- if (_autostartId != 0) {
- // FIXME: Should be a user error
- Q_UNUSED(autostartFound);
- Q_ASSERT(autostartFound);
+ if (_autostartId != 0 && !autostartFound) {
+ _showCustomConfigPanel = true;
+ emit showCustomConfigPanelChanged(true);
}
}
diff --git a/src/AutoPilotPlugins/PX4/AirframeComponentController.h b/src/AutoPilotPlugins/PX4/AirframeComponentController.h
index 0e8b5ced752de8125c2e5edb4e33985f9df32d9d..79cfdcbf8105171b4ccf8983560c9edfcd68c1d8 100644
--- a/src/AutoPilotPlugins/PX4/AirframeComponentController.h
+++ b/src/AutoPilotPlugins/PX4/AirframeComponentController.h
@@ -44,6 +44,8 @@ public:
AirframeComponentController(void);
~AirframeComponentController();
+ Q_PROPERTY(bool showCustomConfigPanel MEMBER _showCustomConfigPanel NOTIFY showCustomConfigPanelChanged)
+
Q_PROPERTY(QVariantList airframeTypes MEMBER _airframeTypes CONSTANT)
Q_PROPERTY(QString currentAirframeType MEMBER _currentAirframeType CONSTANT)
@@ -59,6 +61,7 @@ public:
signals:
void autostartIdChanged(int newAutostartId);
+ void showCustomConfigPanelChanged(bool show);
private:
static bool _typesRegistered;
@@ -69,6 +72,7 @@ private:
QString _currentVehicleName;
int _currentVehicleIndex;
int _autostartId;
+ bool _showCustomConfigPanel;
};
class Airframe : public QObject
diff --git a/src/QmlControls/ViewWithDialog.qml b/src/QmlControls/ViewWithDialog.qml
new file mode 100644
index 0000000000000000000000000000000000000000..61d64c41bbaffb4c7b3c0a5eded26a3af23570d8
--- /dev/null
+++ b/src/QmlControls/ViewWithDialog.qml
@@ -0,0 +1,221 @@
+/*=====================================================================
+
+ QGroundControl Open Source Ground Control Station
+
+ (c) 2009 - 2015 QGROUNDCONTROL PROJECT
+
+ 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 .
+
+ ======================================================================*/
+
+/// @file
+/// @author Don Gagne
+
+import QtQuick 2.3
+import QtQuick.Controls 1.3
+import QtQuick.Dialogs 1.2
+
+import QGroundControl.Controls 1.0
+import QGroundControl.Palette 1.0
+import QGroundControl.ScreenTools 1.0
+import QGroundControl.FactSystem 1.0
+import QGroundControl.FactControls 1.0
+
+Item {
+ property Component viewComponent
+
+ function __showDialog(component, title, charWidth, buttons) {
+ __acceptButton.visible = false
+ __rejectButton.visible = false
+ __dialogCharWidth = charWidth
+ __dialogTitle = title
+
+ if (buttons & StandardButton.Ok) {
+ __acceptButton.text = "Ok"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Open) {
+ __acceptButton.text = "Open"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Save) {
+ __acceptButton.text = "Save"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Cancel) {
+ __rejectButton.text = "Cancel"
+ __rejectButton.visible = true
+ } else if (buttons & StandardButton.Close) {
+ __rejectButton.text = "Cancel"
+ __rejectButton.visible = true
+ } else if (buttons & StandardButton.Apply) {
+ __acceptButton.text = "Apply"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Open) {
+ __acceptButton.text = "Open"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.SaveAll) {
+ __acceptButton.text = "Save All"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Yes) {
+ __acceptButton.text = "Yes"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.YesToAll) {
+ __acceptButton.text = "Yes to All"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.No) {
+ __rejectButton.text = "No"
+ __rejectButton.visible = true
+ } else if (buttons & StandardButton.NoToAll) {
+ __rejectButton.text = "No to All"
+ __rejectButton.visible = true
+ } else if (buttons & StandardButton.Abort) {
+ __rejectButton.text = "Abort"
+ __rejectButton.visible = true
+ } else if (buttons & StandardButton.Retry) {
+ __acceptButton.text = "Retry"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Reset) {
+ __acceptButton.text = "Reset"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.RestoreToDefaults) {
+ __acceptButton.text = "Restore to Defaults"
+ __acceptButton.visible = true
+ } else if (buttons & StandardButton.Ignore) {
+ __acceptButton.text = "Ignore"
+ __acceptButton.visible = true
+ }
+ __dialogComponent = component
+ __viewPanel.enabled = false
+ __dialogOverlay.visible = true
+ }
+
+ function __hideDialog() {
+ __dialogComponent = null
+ __viewPanel.enabled = true
+ __dialogOverlay.visible = false
+ }
+
+ QGCPalette { id: __qgcPal; colorGroupEnabled: true }
+ QGCLabel { id: __textMeasure; text: "X"; visible: false }
+
+ property real __textHeight: __textMeasure.contentHeight
+ property real __textWidth: __textMeasure.contentWidth
+
+ /// The width of the dialog panel in characters
+ property int __dialogCharWidth: 75
+
+ /// The title for the dialog panel
+ property string __dialogTitle
+
+ property Component __dialogComponent
+
+ Component.onCompleted: __viewPanel.item.doWorkAfterComponentCompleted()
+
+ Connections {
+ target: __viewPanel.item
+
+ onShowDialog: __showDialog(component, title, charWidth, buttons)
+ onHideDialog: __hideDialog()
+ }
+
+ Connections {
+ target: __dialogComponentLoader.item
+
+ onHideDialog: __hideDialog()
+ }
+
+ Loader {
+ id: __viewPanel
+ anchors.fill: parent
+ focus: true
+ sourceComponent: viewComponent
+ }
+
+ Item {
+ id: __dialogOverlay
+ visible: false
+ anchors.fill: parent
+ z: 5000
+
+ // This covers the parent with an transparent section
+ Rectangle {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: __dialogPanel.left
+ opacity: 0.80
+ color: __qgcPal.window
+ }
+
+ // This is the main dialog panel which is anchored to the right edge
+ Rectangle {
+ id: __dialogPanel
+ width: __textWidth * __dialogCharWidth
+ height: parent.height
+ anchors.right: parent.right
+ color: __qgcPal.windowShadeDark
+
+ Rectangle {
+ id: __header
+ width: parent.width
+ height: __acceptButton.height
+ color: __qgcPal.windowShade
+
+ function __hidePanel() {
+ __fullPanel.visible = false
+ }
+
+ QGCLabel {
+ x: __textWidth
+ height: parent.height
+ verticalAlignment: Text.AlignVCenter
+ text: __dialogTitle
+ }
+
+ QGCButton {
+ id: __rejectButton
+ anchors.right: __acceptButton.left
+ anchors.bottom: parent.bottom
+
+ onClicked: __dialogComponentLoader.item.reject()
+ }
+
+ QGCButton {
+ id: __acceptButton
+ anchors.right: parent.right
+ primary: true
+
+ onClicked: __dialogComponentLoader.item.accept()
+ }
+ }
+
+ Item {
+ id: __spacer
+ width: 10
+ height: 10
+ anchors.top: __header.bottom
+ }
+
+ Loader {
+ id: __dialogComponentLoader
+ anchors.margins: 5
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: __spacer.bottom
+ anchors.bottom: parent.bottom
+ sourceComponent: __dialogComponent
+ }
+ } // Rectangle - Dialog panel
+ } // Item - Dialog overlay
+}
\ No newline at end of file
diff --git a/src/QmlControls/qmldir b/src/QmlControls/qmldir
index b62af1bcbd73ebb6588a628c0514fd3f90f65902..a588343b36f613226ad807df77765cea3020797e 100644
--- a/src/QmlControls/qmldir
+++ b/src/QmlControls/qmldir
@@ -16,4 +16,5 @@ VehicleRotationCal 1.0 VehicleRotationCal.qml
VehicleSummaryRow 1.0 VehicleSummaryRow.qml
ParameterEditor 1.0 ParameterEditor.qml
ViewWidget 1.0 ViewWidget.qml
+ViewWithDialog 1.0 ViewWithDialog.qml