From 27a9339bce5c56ae98c524d20989bf466d284373 Mon Sep 17 00:00:00 2001
From: Gus Grubba <gus@auterion.com>
Date: Sat, 22 Jun 2019 16:28:14 -0300
Subject: [PATCH] Move PreflightCheckList to custom builds only. The model,
 which used to be implemented within BuiltinPreFlightCheckModel is now within
 the control itself. It is up to the implementer to define a proper model.

---
 custom-example/custom.qrc                          |   1 +
 custom-example/res/PreFlightCheckList.qml          | 175 +++++++++++++++++++++
 custom-example/src/CustomPlugin.h                  |   1 +
 qgroundcontrol.qrc                                 |   2 -
 src/FlightDisplay/BuiltInPreFlightCheckModel.qml   |  88 -----------
 src/FlightDisplay/FlightDisplayView.qml            |  25 ++-
 src/QmlControls/QGroundControl/Controls/qmldir     |   1 -
 .../QGroundControl/FlightDisplay/qmldir            |   1 -
 src/api/QGCOptions.h                               |   7 +-
 9 files changed, 195 insertions(+), 106 deletions(-)
 create mode 100644 custom-example/res/PreFlightCheckList.qml
 delete mode 100644 src/FlightDisplay/BuiltInPreFlightCheckModel.qml

diff --git a/custom-example/custom.qrc b/custom-example/custom.qrc
index 29e58bc..8b2ffc7 100644
--- a/custom-example/custom.qrc
+++ b/custom-example/custom.qrc
@@ -10,6 +10,7 @@
         <file alias="CustomModeIndicator.qml">res/MainToolbar/CustomModeIndicator.qml</file>
         <file alias="CustomMultiVehicleSelector.qml">res/MainToolbar/CustomMultiVehicleSelector.qml</file>
         <file alias="CustomRCRSSIIndicator.qml">res/MainToolbar/CustomRCRSSIIndicator.qml</file>
+        <file alias="PreFlightCheckList.qml">res/PreFlightCheckList.qml</file>
     </qresource>
     <qresource prefix="custom/img">
         <file alias="altitude.svg">res/Images/altitude.svg</file>
diff --git a/custom-example/res/PreFlightCheckList.qml b/custom-example/res/PreFlightCheckList.qml
new file mode 100644
index 0000000..dc3079d
--- /dev/null
+++ b/custom-example/res/PreFlightCheckList.qml
@@ -0,0 +1,175 @@
+/****************************************************************************
+ *
+ *   (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.3
+import QtQuick.Controls 1.2
+import QtQml.Models     2.1
+
+import QGroundControl               1.0
+import QGroundControl.ScreenTools   1.0
+import QGroundControl.Controls      1.0
+import QGroundControl.FlightDisplay 1.0
+
+Rectangle {
+    width:      mainColumn.width  + ScreenTools.defaultFontPixelWidth * 3
+    height:     mainColumn.height + ScreenTools.defaultFontPixelHeight
+    color:      qgcPal.windowShade
+    radius:     3
+
+    PreFlightCheckModel {
+        id:     listModel
+        PreFlightCheckGroup {
+            name: qsTr("Initial checks")
+
+            // Standard check list items (group 0) - Available from the start
+            PreFlightCheckButton {
+                name:           qsTr("Hardware")
+                manualText:     qsTr("Props mounted? Wings secured? Tail secured?")
+            }
+
+            PreFlightBatteryCheck {
+                failurePercent:                 40
+                allowFailurePercentOverride:    false
+            }
+
+            PreFlightSensorsHealthCheck {
+            }
+
+            PreFlightGPSCheck {
+                failureSatCount:        9
+                allowOverrideSatCount:  true
+            }
+
+            PreFlightRCCheck {
+            }
+        }
+
+        PreFlightCheckGroup {
+            name: qsTr("Please arm the vehicle here")
+
+            PreFlightCheckButton {
+                name:            qsTr("Actuators")
+                manualText:      qsTr("Move all control surfaces. Did they work properly?")
+            }
+
+            PreFlightCheckButton {
+                name:            qsTr("Motors")
+                manualText:      qsTr("Propellers free? Then throttle up gently. Working properly?")
+            }
+
+            PreFlightCheckButton {
+                name:        qsTr("Mission")
+                manualText:  qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).")
+            }
+
+            PreFlightSoundCheck {
+            }
+        }
+
+        PreFlightCheckGroup {
+            name: qsTr("Last preparations before launch")
+
+            // Check list item group 2 - Final checks before launch
+            PreFlightCheckButton {
+                name:        qsTr("Payload")
+                manualText:  qsTr("Configured and started? Payload lid closed?")
+            }
+
+            PreFlightCheckButton {
+                name:        "Wind & weather"
+                manualText:  qsTr("OK for your platform? Lauching into the wind?")
+            }
+
+            PreFlightCheckButton {
+                name:        qsTr("Flight area")
+                manualText:  qsTr("Launch area and path free of obstacles/people?")
+            }
+        }
+    }
+
+    property bool _passed:  false
+
+    function _handleGroupPassedChanged(index, passed) {
+        if (passed) {
+            // Collapse current group
+            var group = checkListRepeater.itemAt(index)
+            group._checked = false
+            // Expand next group
+            if (index + 1 < checkListRepeater.count) {
+                group = checkListRepeater.itemAt(index + 1)
+                group.enabled = true
+                group._checked = true
+            }
+        }
+        _passed = passed
+    }
+
+    // We delay the updates when a group passes so the user can see all items green for a moment prior to hiding
+    Timer {
+        id:         delayedGroupPassed
+        interval:   750
+
+        property int index
+
+        onTriggered: _handleGroupPassedChanged(index, true /* passed */)
+    }
+
+    Column {
+        id:                     mainColumn
+        width:                  40  * ScreenTools.defaultFontPixelWidth
+        spacing:                0.8 * ScreenTools.defaultFontPixelWidth
+        anchors.left:           parent.left
+        anchors.top:            parent.top
+        anchors.topMargin:      0.6 * ScreenTools.defaultFontPixelWidth
+        anchors.leftMargin:     1.5 * ScreenTools.defaultFontPixelWidth
+
+        function groupPassedChanged(index, passed) {
+            if (passed) {
+                delayedGroupPassed.index = index
+                delayedGroupPassed.restart()
+            } else {
+                _handleGroupPassedChanged(index, passed)
+            }
+        }
+
+        // Header/title of checklist
+        Item {
+            width:      parent.width
+            height:     1.75 * ScreenTools.defaultFontPixelHeight
+
+            QGCLabel {
+                text:                   qsTr("Pre-Flight Checklist %1").arg(_passed ? qsTr("(passed)") : "")
+                anchors.left:           parent.left
+                anchors.verticalCenter: parent.verticalCenter
+                font.pointSize:         ScreenTools.mediumFontPointSize
+            }
+            QGCButton {
+                width:                  1.2 * ScreenTools.defaultFontPixelHeight
+                height:                 1.2 * ScreenTools.defaultFontPixelHeight
+                anchors.right:          parent.right
+                anchors.verticalCenter: parent.verticalCenter
+                tooltip:                qsTr("Reset the checklist (e.g. after a vehicle reboot)")
+
+                onClicked:              model.reset()
+
+                QGCColoredImage {
+                    source:         "/qmlimages/MapSyncBlack.svg"
+                    color:          qgcPal.buttonText
+                    anchors.fill:   parent
+                }
+            }
+        }
+
+        // All check list items
+        Repeater {
+            id:     checkListRepeater
+            model:  listModel
+        }
+    }
+}
diff --git a/custom-example/src/CustomPlugin.h b/custom-example/src/CustomPlugin.h
index be8af12..3d31314 100644
--- a/custom-example/src/CustomPlugin.h
+++ b/custom-example/src/CustomPlugin.h
@@ -43,6 +43,7 @@ public:
     CustomOptions(CustomPlugin*, QObject* parent = nullptr);
     bool        wifiReliableForCalibration      () const final { return true; }
     QUrl        flyViewOverlay                  () const final { return QUrl::fromUserInput("qrc:/custom/CustomFlyView.qml"); }
+    QUrl        preFlightChecklistUrl           () const final { return QUrl::fromUserInput("qrc:/custom/PreFlightCheckList.qml"); }
     //-- We have our own toolbar
     QUrl        mainToolbarUrl                  () const final { return QUrl::fromUserInput("qrc:/custom/CustomMainToolBar.qml"); }
     QUrl        planToolbarUrl                  () const final { return QUrl::fromUserInput("qrc:/custom/CustomMainToolBar.qml"); }
diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 3d0c0b0..7abcf7d 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -94,7 +94,6 @@
         <file alias="QGroundControl/Controls/PIDTuning.qml">src/QmlControls/PIDTuning.qml</file>
         <file alias="QGroundControl/Controls/PreFlightCheckButton.qml">src/QmlControls/PreFlightCheckButton.qml</file>
         <file alias="QGroundControl/Controls/PreFlightCheckGroup.qml">src/QmlControls/PreFlightCheckGroup.qml</file>
-        <file alias="QGroundControl/Controls/PreFlightCheckList.qml">src/QmlControls/PreFlightCheckList.qml</file>
         <file alias="QGroundControl/Controls/PreFlightCheckModel.qml">src/QmlControls/PreFlightCheckModel.qml</file>
         <file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file>
         <file alias="QGroundControl/Controls/QGCCheckBox.qml">src/QmlControls/QGCCheckBox.qml</file>
@@ -152,7 +151,6 @@
         <file alias="QGroundControl/FactControls/FactTextFieldSlider.qml">src/FactSystem/FactControls/FactTextFieldSlider.qml</file>
         <file alias="QGroundControl/FactControls/FactValueSlider.qml">src/FactSystem/FactControls/FactValueSlider.qml</file>
         <file alias="QGroundControl/FactControls/qmldir">src/QmlControls/QGroundControl/FactControls/qmldir</file>
-        <file alias="QGroundControl/FlightDisplay/BuiltInPreFlightCheckModel.qml">src/FlightDisplay/BuiltInPreFlightCheckModel.qml</file>
         <file alias="QGroundControl/FlightDisplay/FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file>
         <file alias="QGroundControl/FlightDisplay/FlightDisplayViewMap.qml">src/FlightDisplay/FlightDisplayViewMap.qml</file>
         <file alias="QGroundControl/FlightDisplay/FlightDisplayViewVideo.qml">src/FlightDisplay/FlightDisplayViewVideo.qml</file>
diff --git a/src/FlightDisplay/BuiltInPreFlightCheckModel.qml b/src/FlightDisplay/BuiltInPreFlightCheckModel.qml
deleted file mode 100644
index c39a639..0000000
--- a/src/FlightDisplay/BuiltInPreFlightCheckModel.qml
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
- *
- *   (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.3
-import QtQml.Models                 2.1
-
-import QGroundControl               1.0
-import QGroundControl.FlightDisplay 1.0
-import QGroundControl.ScreenTools   1.0
-import QGroundControl.Controls      1.0
-import QGroundControl.Palette       1.0
-import QGroundControl.Vehicle       1.0
-
-PreFlightCheckModel {
-    PreFlightCheckGroup {
-        name: qsTr("Initial checks")
-
-        // Standard check list items (group 0) - Available from the start
-        PreFlightCheckButton {
-            name:           qsTr("Hardware")
-            manualText:     qsTr("Props mounted? Wings secured? Tail secured?")
-        }
-
-        PreFlightBatteryCheck {
-            failurePercent:                 40
-            allowFailurePercentOverride:    false
-        }
-
-        PreFlightSensorsHealthCheck {
-        }
-
-        PreFlightGPSCheck {
-            failureSatCount:        9
-            allowOverrideSatCount:  true
-        }
-
-        PreFlightRCCheck {
-        }
-    }
-
-    PreFlightCheckGroup {
-        name: qsTr("Please arm the vehicle here")
-
-        PreFlightCheckButton {
-            name:            qsTr("Actuators")
-            manualText:      qsTr("Move all control surfaces. Did they work properly?")
-        }
-
-        PreFlightCheckButton {
-            name:            qsTr("Motors")
-            manualText:      qsTr("Propellers free? Then throttle up gently. Working properly?")
-        }
-
-        PreFlightCheckButton {
-            name:        qsTr("Mission")
-            manualText:  qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).")
-        }
-
-        PreFlightSoundCheck {
-        }
-    }
-
-    PreFlightCheckGroup {
-        name: qsTr("Last preparations before launch")
-
-        // Check list item group 2 - Final checks before launch
-        PreFlightCheckButton {
-            name:        qsTr("Payload")
-            manualText:  qsTr("Configured and started? Payload lid closed?")
-        }
-
-        PreFlightCheckButton {
-            name:        "Wind & weather"
-            manualText:  qsTr("OK for your platform? Lauching into the wind?")
-        }
-
-        PreFlightCheckButton {
-            name:        qsTr("Flight area")
-            manualText:  qsTr("Launch area and path free of obstacles/people?")
-        }
-    }
-} // Object Model
diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml
index 11c62af..60e61ee 100644
--- a/src/FlightDisplay/FlightDisplayView.qml
+++ b/src/FlightDisplay/FlightDisplayView.qml
@@ -48,7 +48,7 @@ Item {
     property var    _geoFenceController:            _planController.geoFenceController
     property var    _rallyPointController:          _planController.rallyPointController
     property bool   _isPipVisible:                  QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
-    property bool   _useChecklist:                  QGroundControl.settingsManager.appSettings.useChecklist.rawValue
+    property bool   _useChecklist:                  QGroundControl.settingsManager.appSettings.useChecklist.rawValue && QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length
     property real   _savedZoomLevel:                0
     property real   _margins:                       ScreenTools.defaultFontPixelWidth / 2
     property real   _pipSize:                       mainWindow.width * 0.2
@@ -115,10 +115,6 @@ Item {
         return true;
     }
 
-    BuiltInPreFlightCheckModel {
-        id: preFlightCheckModel
-    }
-
     Connections {
         target:                     _missionController
         onResumeMissionUploadFail:  guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionUploadFail)
@@ -143,6 +139,9 @@ Item {
         if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) {
             flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay
         }
+        if(QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length) {
+            checkList.source = QGroundControl.corePlugin.options.preFlightChecklistUrl
+        }
     }
 
     // The following code is used to track vehicle states such that we prompt to remove mission from vehicle when mission completes
@@ -800,19 +799,19 @@ Item {
         id:             checklistDropPanel
         x:              Math.round((mainWindow.width  - width)  * 0.5)
         y:              Math.round((mainWindow.height - height) * 0.5)
-        height:         checkList.height
-        width:          checkList.width
+        height:         checkList.width
+        width:          checkList.height
         modal:          true
         focus:          true
         closePolicy:    Popup.CloseOnEscape | Popup.CloseOnPressOutside
         background: Rectangle {
-            anchors.fill:   parent
-            color:          Qt.rgba(0,0,0,0)
-            clip:           true
+            anchors.fill:  parent
+            color:      Qt.rgba(0,0,0,0)
+            clip:       true
         }
-        PreFlightCheckList {
-            id:     checkList
-            model:  preFlightCheckModel
+        Loader {
+            id:         checkList
+            anchors.centerIn: parent
         }
     }
 
diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir
index b96999f..6a7e1b2 100644
--- a/src/QmlControls/QGroundControl/Controls/qmldir
+++ b/src/QmlControls/QGroundControl/Controls/qmldir
@@ -36,7 +36,6 @@ ParameterEditorDialog   1.0 ParameterEditorDialog.qml
 PIDTuning               1.0 PIDTuning.qml
 PreFlightCheckButton    1.0 PreFlightCheckButton.qml
 PreFlightCheckGroup     1.0 PreFlightCheckGroup.qml
-PreFlightCheckList      1.0 PreFlightCheckList.qml
 PreFlightCheckModel     1.0 PreFlightCheckModel.qml
 QGCButton               1.0 QGCButton.qml
 QGCCheckBox             1.0 QGCCheckBox.qml
diff --git a/src/QmlControls/QGroundControl/FlightDisplay/qmldir b/src/QmlControls/QGroundControl/FlightDisplay/qmldir
index 69dca16..c06aacc 100644
--- a/src/QmlControls/QGroundControl/FlightDisplay/qmldir
+++ b/src/QmlControls/QGroundControl/FlightDisplay/qmldir
@@ -1,6 +1,5 @@
 Module QGroundControl.FlightDisplay
 
-BuiltInPreFlightCheckModel  1.0 BuiltInPreFlightCheckModel.qml
 FlightDisplayView           1.0 FlightDisplayView.qml
 FlightDisplayViewMap        1.0 FlightDisplayViewMap.qml
 FlightDisplayViewVideo      1.0 FlightDisplayViewVideo.qml
diff --git a/src/api/QGCOptions.h b/src/api/QGCOptions.h
index b2b6ebc..ac660fa 100644
--- a/src/api/QGCOptions.h
+++ b/src/api/QGCOptions.h
@@ -30,6 +30,7 @@ public:
     Q_PROPERTY(bool                     enablePlanViewSelector          READ enablePlanViewSelector         CONSTANT)
     Q_PROPERTY(CustomInstrumentWidget*  instrumentWidget                READ instrumentWidget               CONSTANT)
     Q_PROPERTY(QUrl                     flyViewOverlay                  READ flyViewOverlay                 CONSTANT)
+    Q_PROPERTY(QUrl                     preFlightChecklistUrl           READ preFlightChecklistUrl          CONSTANT)
 
     Q_PROPERTY(QUrl                     mainToolbarUrl                  READ mainToolbarUrl                 CONSTANT)
     Q_PROPERTY(QUrl                     planToolbarUrl                  READ planToolbarUrl                 CONSTANT)
@@ -83,10 +84,14 @@ public:
 
     /// Should the mission status indicator (Plan View) be shown?
     /// @return Yes or no
-    virtual bool        showMissionStatus           () { return true; }
+    virtual bool    showMissionStatus               () { return true; }
 
     /// Allows access to the full fly view window
     virtual QUrl    flyViewOverlay                  () const { return QUrl(); }
+
+    /// Provides an optional preflight checklist
+    virtual QUrl    preFlightChecklistUrl           () const { return QUrl(); }
+
     /// Allows replacing the toolbar
     virtual QUrl    mainToolbarUrl                  () const;
     virtual QUrl    planToolbarUrl                  () const;