From 3f8dc069a554a0b89756446d680b3bb2f1cad90a Mon Sep 17 00:00:00 2001
From: Don Gagne <Don@don-laptop.local>
Date: Sun, 10 Dec 2017 12:50:40 -0800
Subject: [PATCH] QGCViewDialog controls can now call QGCView.showDialog to
 stack dialogs

---
 qgroundcontrol.qrc                             |   1 +
 src/QmlControls/QGCView.qml                    | 228 +++----------------------
 src/QmlControls/QGCViewDialog.qml              |  19 +--
 src/QmlControls/QGCViewDialogContainer.qml     | 190 +++++++++++++++++++++
 src/QmlControls/QGroundControl.Controls.qmldir |   1 +
 5 files changed, 220 insertions(+), 219 deletions(-)
 create mode 100644 src/QmlControls/QGCViewDialogContainer.qml

diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 8fccc74..b6a348f 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -97,6 +97,7 @@
         <file alias="QGroundControl/Controls/QGCToolBarButton.qml">src/QmlControls/QGCToolBarButton.qml</file>
         <file alias="QGroundControl/Controls/QGCView.qml">src/QmlControls/QGCView.qml</file>
         <file alias="QGroundControl/Controls/QGCViewDialog.qml">src/QmlControls/QGCViewDialog.qml</file>
+        <file alias="QGroundControl/Controls/QGCViewDialogContainer.qml">src/QmlControls/QGCViewDialogContainer.qml</file>
         <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/qmldir">src/QmlControls/QGroundControl.Controls.qmldir</file>
diff --git a/src/QmlControls/QGCView.qml b/src/QmlControls/QGCView.qml
index 3bced36..1591822 100644
--- a/src/QmlControls/QGCView.qml
+++ b/src/QmlControls/QGCView.qml
@@ -26,75 +26,12 @@ FactPanel {
 
     property var    qgcView:               _rootItem  ///< Used by Fact controls for validation dialogs
     property bool   completedSignalled:   false
-    property real   topDialogMargin:      0           ///< Set a top margin for dialog
     property var    viewPanel
 
     /// This is signalled when the top level Item reaches Component.onCompleted. This allows
     /// the view subcomponent to connect to this signal and do work once the full ui is ready
     /// to go.
-    signal completed        
-
-    function _setupDialogButtons(buttons) {
-        _acceptButton.visible = false
-        _rejectButton.visible = false
-
-        // Accept role buttons
-        if (buttons & StandardButton.Ok) {
-            _acceptButton.text = qsTr("Ok")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Open) {
-            _acceptButton.text = qsTr("Open")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Save) {
-            _acceptButton.text = qsTr("Save")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Apply) {
-            _acceptButton.text = qsTr("Apply")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Open) {
-            _acceptButton.text = qsTr("Open")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.SaveAll) {
-            _acceptButton.text = qsTr("Save All")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Yes) {
-            _acceptButton.text = qsTr("Yes")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.YesToAll) {
-            _acceptButton.text = qsTr("Yes to All")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Retry) {
-            _acceptButton.text = qsTr("Retry")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Reset) {
-            _acceptButton.text = qsTr("Reset")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.RestoreToDefaults) {
-            _acceptButton.text = qsTr("Restore to Defaults")
-            _acceptButton.visible = true
-        } else if (buttons & StandardButton.Ignore) {
-            _acceptButton.text = qsTr("Ignore")
-            _acceptButton.visible = true
-        }
-
-        // Reject role buttons
-        if (buttons & StandardButton.Cancel) {
-            _rejectButton.text = qsTr("Cancel")
-            _rejectButton.visible = true
-        } else if (buttons & StandardButton.Close) {
-            _rejectButton.text = qsTr("Close")
-            _rejectButton.visible = true
-        } else if (buttons & StandardButton.No) {
-            _rejectButton.text = qsTr("No")
-            _rejectButton.visible = true
-        } else if (buttons & StandardButton.NoToAll) {
-            _rejectButton.text = qsTr("No to All")
-            _rejectButton.visible = true
-        } else if (buttons & StandardButton.Abort) {
-            _rejectButton.text = qsTr("Abort")
-            _rejectButton.visible = true
-        }
-    }
+    signal completed
 
     function _checkForEarlyDialog(title) {
         if (!completedSignalled) {
@@ -116,60 +53,36 @@ FactPanel {
             return
         }
 
-        _rejectButton.enabled = true
-        _acceptButton.enabled = true
-
-        _dialogCharWidth = charWidth
-        _dialogTitle = title
-
-        _setupDialogButtons(buttons)
-
-        _dialogComponent = component
-        viewPanel.enabled = false
-        _dialogOverlay.visible = true
-    }
-
-    function showMessage(title, message, buttons) {
-        if (_checkForEarlyDialog(title)) {
+        var dialogComponent = Qt.createComponent("QGCViewDialogContainer.qml")
+        if (dialogComponent.status === Component.Error) {
+            console.log("Error loading QGCViewDialogContainer.qml: ", dialogComponent.errorString())
             return
         }
-
-        _rejectButton.enabled = true
-        _acceptButton.enabled = true
-
-        _dialogCharWidth = showDialogDefaultWidth
-        _dialogTitle = title
-        _messageDialogText = message
-
-        _setupDialogButtons(buttons)
-
-        _dialogComponent = _messageDialog
+        var dialogWidth = charWidth == showDialogFullWidth ? parent.width : ScreenTools.defaultFontPixelWidth * charWidth
+        var dialog = dialogComponent.createObject(_rootItem,
+                                                  {
+                                                      "anchors.fill":       _rootItem,
+                                                      "dialogWidth":        dialogWidth,
+                                                      "dialogTitle":        title,
+                                                      "dialogComponent":    component,
+                                                      "viewPanel":          viewPanel
+                                                  })
+        dialog.setupDialogButtons(buttons)
         viewPanel.enabled = false
-        _dialogOverlay.visible = true
     }
 
-    function hideDialog() {
-        viewPanel.enabled = true
-        _dialogComponent = null
-        _dialogOverlay.visible = false
+    function showMessage(title, message, buttons) {
+        _messageDialogText = message
+        showDialog(_messageDialog, title, showDialogDefaultWidth, buttons)
     }
 
     QGCPalette { id: _qgcPal; colorGroupEnabled: true }
-    QGCLabel { id: _textMeasure; text: "X"; visible: false }
 
-    property real defaultTextHeight: _textMeasure.contentHeight
-    property real defaultTextWidth:  _textMeasure.contentWidth
-
-    /// The width of the dialog panel in characters
-    property int _dialogCharWidth: 75
-
-    /// The title for the dialog panel
-    property string _dialogTitle
+    property real defaultTextWidth:     ScreenTools.defaultFontPixelWidth
+    property real defaultTextHeight:    ScreenTools.defaultFontPixelHeight
 
     property string _messageDialogText
 
-    property Component _dialogComponent
-
     function _signalCompleted() {
         // When we use this control inside a QGCQmlWidgetHolder Component.onCompleted is signalled
         // before the width and height are adjusted. So we need to wait for width and heigth to be
@@ -184,109 +97,6 @@ FactPanel {
     onWidthChanged:         _signalCompleted()
     onHeightChanged:        _signalCompleted()
 
-    Connections {
-        target: _dialogComponentLoader.item
-
-        onHideDialog: _rootItem.hideDialog()
-    }
-
-    Item {
-        id:             _dialogOverlay
-        visible:        false
-        anchors.fill:   parent
-        z:              5000
-
-        // This covers the parent with an transparent section
-        Rectangle {
-            id:             _transparentSection
-            height:         ScreenTools.availableHeight ? ScreenTools.availableHeight : parent.height
-            anchors.bottom: parent.bottom
-            anchors.left:   parent.left
-            anchors.right:  _dialogPanel.left
-            opacity:        0.0
-            color:          _qgcPal.window
-        }
-
-        // This is the main dialog panel which is anchored to the right edge
-        Rectangle {
-            id:                 _dialogPanel
-            width:              _dialogCharWidth == showDialogFullWidth ? parent.width : defaultTextWidth * _dialogCharWidth
-            anchors.topMargin:  topDialogMargin
-            height:             ScreenTools.availableHeight ? ScreenTools.availableHeight : parent.height
-            anchors.bottom:     parent.bottom
-            anchors.right:      parent.right
-            color:              _qgcPal.windowShadeDark
-
-            Rectangle {
-                id:     _header
-                width:  parent.width
-                height: _acceptButton.visible ? _acceptButton.height : _rejectButton.height
-                color:  _qgcPal.windowShade
-
-                function _hidePanel() {
-                    _fullPanel.visible = false
-                }
-
-                QGCLabel {
-                    x:                  defaultTextWidth
-                    height:             parent.height
-                    verticalAlignment:	Text.AlignVCenter
-                    text:               _dialogTitle
-                }
-
-                QGCButton {
-                    id:             _rejectButton
-                    anchors.right:  _acceptButton.visible ?  _acceptButton.left : parent.right
-                    anchors.bottom: parent.bottom
-
-                    onClicked: {
-                        enabled = false // prevent multiple clicks
-                        _dialogComponentLoader.item.reject()
-                        if (!viewPanel.enabled) {
-                            // Dialog was not closed, re-enable button
-                            enabled = true
-                        }
-                    }
-                }
-
-                QGCButton {
-                    id:             _acceptButton
-                    anchors.right:  parent.right
-                    primary:        true
-
-                    onClicked: {
-                        enabled = false // prevent multiple clicks
-                       _dialogComponentLoader.item.accept()
-                        if (!viewPanel.enabled) {
-                            // Dialog was not closed, re-enable button
-                            enabled = true
-                        }
-                    }
-                }
-            }
-
-            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
-
-                property bool acceptAllowed: _acceptButton.visible
-                property bool rejectAllowed: _rejectButton.visible
-            }
-        } // Rectangle - Dialog panel
-    } // Item - Dialog overlay
-
     Component {
         id: _messageDialog
 
diff --git a/src/QmlControls/QGCViewDialog.qml b/src/QmlControls/QGCViewDialog.qml
index 5e6b704..982b5fe 100644
--- a/src/QmlControls/QGCViewDialog.qml
+++ b/src/QmlControls/QGCViewDialog.qml
@@ -7,22 +7,21 @@
  *
  ****************************************************************************/
 
-
-/// @file
-///     @author Don Gagne <don@thegagnes.com>
-
-import QtQuick 2.3
+import QtQuick          2.3
 import QtQuick.Controls 1.2
 
-import QGroundControl.Controls 1.0
-import QGroundControl.Palette 1.0
-
-import QGroundControl.FactSystem 1.0
-import QGroundControl.FactControls 1.0
+import QGroundControl.Controls      1.0
+import QGroundControl.Palette       1.0
+import QGroundControl.FactSystem    1.0
+import QGroundControl.FactControls  1.0
+import QGroundControl.ScreenTools   1.0
 
 FactPanel {
     property var qgcTextFieldforwardKeysTo: this    ///< Causes all QGCTextFields to forward keys here if they have focus
 
+    property real defaultTextWidth:     ScreenTools.defaultFontPixelWidth
+    property real defaultTextHeight:    ScreenTools.defaultFontPixelHeight
+
     QGCPalette { id: __qgcPal; colorGroupEnabled: enabled }
 
     signal hideDialog
diff --git a/src/QmlControls/QGCViewDialogContainer.qml b/src/QmlControls/QGCViewDialogContainer.qml
new file mode 100644
index 0000000..dda8209
--- /dev/null
+++ b/src/QmlControls/QGCViewDialogContainer.qml
@@ -0,0 +1,190 @@
+/****************************************************************************
+ *
+ *   (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 QtQuick.Dialogs  1.2
+
+import QGroundControl.Controls      1.0
+import QGroundControl.Palette       1.0
+import QGroundControl.ScreenTools   1.0
+
+Item {
+    id: _root
+    z:  5000
+
+    property alias  dialogWidth:     _dialogPanel.width
+    property alias  dialogTitle:     titleLabel.text
+    property alias  dialogComponent: _dialogComponentLoader.sourceComponent
+    property var    viewPanel
+
+    property real _defaultTextHeight:   _textMeasure.contentHeight
+    property real _defaultTextWidth:    _textMeasure.contentWidth
+
+    function setupDialogButtons(buttons) {
+        _acceptButton.visible = false
+        _rejectButton.visible = false
+
+        // Accept role buttons
+        if (buttons & StandardButton.Ok) {
+            _acceptButton.text = qsTr("Ok")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Open) {
+            _acceptButton.text = qsTr("Open")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Save) {
+            _acceptButton.text = qsTr("Save")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Apply) {
+            _acceptButton.text = qsTr("Apply")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Open) {
+            _acceptButton.text = qsTr("Open")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.SaveAll) {
+            _acceptButton.text = qsTr("Save All")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Yes) {
+            _acceptButton.text = qsTr("Yes")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.YesToAll) {
+            _acceptButton.text = qsTr("Yes to All")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Retry) {
+            _acceptButton.text = qsTr("Retry")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Reset) {
+            _acceptButton.text = qsTr("Reset")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.RestoreToDefaults) {
+            _acceptButton.text = qsTr("Restore to Defaults")
+            _acceptButton.visible = true
+        } else if (buttons & StandardButton.Ignore) {
+            _acceptButton.text = qsTr("Ignore")
+            _acceptButton.visible = true
+        }
+
+        // Reject role buttons
+        if (buttons & StandardButton.Cancel) {
+            _rejectButton.text = qsTr("Cancel")
+            _rejectButton.visible = true
+        } else if (buttons & StandardButton.Close) {
+            _rejectButton.text = qsTr("Close")
+            _rejectButton.visible = true
+        } else if (buttons & StandardButton.No) {
+            _rejectButton.text = qsTr("No")
+            _rejectButton.visible = true
+        } else if (buttons & StandardButton.NoToAll) {
+            _rejectButton.text = qsTr("No to All")
+            _rejectButton.visible = true
+        } else if (buttons & StandardButton.Abort) {
+            _rejectButton.text = qsTr("Abort")
+            _rejectButton.visible = true
+        }
+    }
+
+    Connections {
+        target: _dialogComponentLoader.item
+
+        onHideDialog: {
+            viewPanel.enabled = true
+            _root.destroy()
+        }
+    }
+
+    QGCPalette { id: _qgcPal; colorGroupEnabled: true }
+    QGCLabel { id: _textMeasure; text: "X"; visible: false }
+
+    Rectangle {
+        anchors.top:    parent.top
+        anchors.bottom: parent.bottom
+        anchors.left:   parent.left
+        anchors.right:  _dialogPanel.left
+        opacity:        0.5
+        color:          _qgcPal.window
+        z:              5000
+    }
+
+    // This is the main dialog panel which is anchored to the right edge
+    Rectangle {
+        id:                 _dialogPanel
+        height:             ScreenTools.availableHeight ? ScreenTools.availableHeight : parent.height
+        anchors.bottom:     parent.bottom
+        anchors.right:      parent.right
+        color:              _qgcPal.windowShadeDark
+
+        Rectangle {
+            id:     _header
+            width:  parent.width
+            height: _acceptButton.visible ? _acceptButton.height : _rejectButton.height
+            color:  _qgcPal.windowShade
+
+            function _hidePanel() {
+                _fullPanel.visible = false
+            }
+
+            QGCLabel {
+                id:                 titleLabel
+                x:                  _defaultTextWidth
+                height:             parent.height
+                verticalAlignment:	Text.AlignVCenter
+            }
+
+            QGCButton {
+                id:             _rejectButton
+                anchors.right:  _acceptButton.visible ?  _acceptButton.left : parent.right
+                anchors.bottom: parent.bottom
+
+                onClicked: {
+                    enabled = false // prevent multiple clicks
+                    _dialogComponentLoader.item.reject()
+                    if (!viewPanel.enabled) {
+                        // Dialog was not closed, re-enable button
+                        enabled = true
+                    }
+                }
+            }
+
+            QGCButton {
+                id:             _acceptButton
+                anchors.right:  parent.right
+                primary:        true
+
+                onClicked: {
+                    enabled = false // prevent multiple clicks
+                    _dialogComponentLoader.item.accept()
+                    if (!viewPanel.enabled) {
+                        // Dialog was not closed, re-enable button
+                        enabled = true
+                    }
+                }
+            }
+        }
+
+        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
+
+            property bool acceptAllowed: _acceptButton.visible
+            property bool rejectAllowed: _rejectButton.visible
+        }
+    } // Rectangle - Dialog panel
+}
diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir
index 514aeb1..2701dbe 100644
--- a/src/QmlControls/QGroundControl.Controls.qmldir
+++ b/src/QmlControls/QGroundControl.Controls.qmldir
@@ -57,6 +57,7 @@ QGCTextField            1.0 QGCTextField.qml
 QGCToolBarButton        1.0 QGCToolBarButton.qml
 QGCView                 1.0 QGCView.qml
 QGCViewDialog           1.0 QGCViewDialog.qml
+QGCViewDialogContainer  1.0 QGCViewDialogContainer.qml
 QGCViewMessage          1.0 QGCViewMessage.qml
 QGCViewPanel            1.0 QGCViewPanel.qml
 RoundButton             1.0 RoundButton.qml