Commit fc550843 authored by Valentin Platzgummer's avatar Valentin Platzgummer

resizing issue: measurement item editor solved

parent ab5abb37
...@@ -7,9 +7,15 @@ import QGroundControl.Controls 1.0 ...@@ -7,9 +7,15 @@ import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0 import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
GridLayout { import QGroundControl.Palette 1.0
Rectangle {
id: _root id: _root
width: mainGrid.width
height: mainGrid.height
color: qgcPal.windowShadeDark
property bool checked: true property bool checked: true
property var missionItem: undefined property var missionItem: undefined
property int availableWidth: 300 property int availableWidth: 300
...@@ -21,10 +27,6 @@ GridLayout { ...@@ -21,10 +27,6 @@ GridLayout {
property var _areaData: missionItem.areaData property var _areaData: missionItem.areaData
property real _margin: ScreenTools.defaultFontPixelWidth / 2 property real _margin: ScreenTools.defaultFontPixelWidth / 2
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Component.onCompleted: { Component.onCompleted: {
console.assert(missionItem !== undefined, console.assert(missionItem !== undefined,
"please set the missionItem property") "please set the missionItem property")
...@@ -41,186 +43,196 @@ GridLayout { ...@@ -41,186 +43,196 @@ GridLayout {
} }
} }
QGCLabel { GridLayout {
text: _root.errorString id: mainGrid
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
Layout.fillWidth: true
visible: !_root.areasCorrect
}
ExclusiveGroup { width: availableWidth
id: areaGroup columnSpacing: _margin
} rowSpacing: _margin
columns: 2
Repeater { QGCLabel {
id: areaSelector text: _root.errorString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
Layout.fillWidth: true
visible: !_root.areasCorrect
}
property int selectedIndex: -1 ExclusiveGroup {
id: areaGroup
}
model: _missionItem.areaData.areaList Repeater {
delegate: QGCRadioButton { id: areaSelector
text: object.objectName
checkable: _root.checked
Layout.fillWidth: true
Layout.columnSpan: 2
onCheckedChanged: { property int selectedIndex: -1
if (checked) {
areaSelector.selectedIndex = index model: _missionItem.areaData.areaList
delegate: QGCRadioButton {
text: object.objectName
checkable: _root.checked
Layout.fillWidth: true
Layout.columnSpan: 2
onCheckedChanged: {
if (checked) {
areaSelector.selectedIndex = index
}
} }
}
Component.onCompleted: { Component.onCompleted: {
if (index === 0) { if (index === 0) {
checked = true checked = true
}
object.interactive = Qt.binding(function () {
return checked && _root.checked
})
} }
object.interactive = Qt.binding(function () {
return checked && _root.checked
})
} }
} } // area Repeater
} // area Repeater
ColumnLayout { ColumnLayout {
id: editorParent id: editorParent
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
Layout.columnSpan: 2 Layout.columnSpan: 2
} }
Repeater { Repeater {
id: areaEditorRepeater id: areaEditorRepeater
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
model: _missionItem.areaData.areaList model: _missionItem.areaData.areaList
delegate: Item { delegate: Item {
id: editor id: editor
visible: index == areaSelector.selectedIndex visible: index == areaSelector.selectedIndex
property var _visualItem: undefined property var _visualItem: undefined
property var geoArea: object property var geoArea: object
Component.onCompleted: { Component.onCompleted: {
if (geoArea.editorQML && !_visualItem) { if (geoArea.editorQML && !_visualItem) {
var component = Qt.createComponent(geoArea.editorQML) var component = Qt.createComponent(geoArea.editorQML)
if (component.status === Component.Error) { if (component.status === Component.Error) {
console.log("Error loading Qml: ", geoArea.editorQML, console.log("Error loading Qml: ",
component.errorString()) geoArea.editorQML,
} else { component.errorString())
_visualItem = component.createObject(editorParent, { } else {
"geoArea": editor.geoArea, _visualItem = component.createObject(editorParent, {
"visible": Qt.binding(function () { "geoArea": editor.geoArea,
return editor.visible "visible": Qt.binding(
}), function () {
"availableWidth": Qt.binding( return editor.visible
function () { }),
return editorParent.width "availableWidth": Qt.binding(function () {
}) return editorParent.width
}) })
})
}
} }
} }
}
Component.onDestruction: { Component.onDestruction: {
if (_visualItem) { if (_visualItem) {
_visualItem.destroy() _visualItem.destroy()
}
} }
} } // editor
} // editor } // areaEditorRepeater
} // areaEditorRepeater
SectionHeader {
id: commandsHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
text: qsTr("Commands")
}
GridLayout {
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Layout.columnSpan: 2
Layout.fillWidth: true
visible: commandsHeader.checked
QGCButton { SectionHeader {
text: "Intersection" id: commandsHeader
enabled: _root.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
onClicked: { text: qsTr("Commands")
_areaData.intersection()
}
} }
QGCButton { GridLayout {
text: "Reset" columnSpacing: _margin
onClicked: { rowSpacing: _margin
_root.reset() columns: 2
} Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
} visible: commandsHeader.checked
QGCButton {
text: "Intersection"
enabled: _root.checked
Layout.fillWidth: true
Layout.columnSpan: parent.columns
onClicked: {
_areaData.intersection()
}
}
QGCButton {
text: "Reset"
onClicked: {
_root.reset()
}
Layout.fillWidth: true
}
QGCButton { QGCButton {
text: "Abort" text: "Abort"
onClicked: { onClicked: {
_root.abort() _root.abort()
}
Layout.fillWidth: true
} }
Layout.fillWidth: true
} }
}
SectionHeader { SectionHeader {
id: hintHeader id: hintHeader
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
text: qsTr("Hints") text: qsTr("Hints")
} }
GridLayout { GridLayout {
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
columns: 2 columns: 2
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
visible: hintHeader.checked visible: hintHeader.checked
QGCLabel { QGCLabel {
id: hintLabel id: hintLabel
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
text: qsTr("Use the Intersection button to clip the Measurement Area(s). text: qsTr("Use the Intersection button to clip the Measurement Area(s).
Use the Reset button to restore the areas to the state before entering this tab. Use the Reset button to restore the areas to the state before entering this tab.
Use the Abort button to reset the areas and leave the tab.") Use the Abort button to reset the areas and leave the tab.")
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
}
} }
}
Timer { Timer {
id: areasCorrectTimer id: areasCorrectTimer
running: false running: false
interval: 100 interval: 100
repeat: true repeat: true
onTriggered: { onTriggered: {
_root.areasCorrect = _missionItem.areaData.isCorrect( _root.areasCorrect = _missionItem.areaData.isCorrect(
false /*show gui message*/ false /*show gui message*/
) )
if (!_root.areasCorrect) { if (!_root.areasCorrect) {
_root.errorString = _missionItem.areaData.errorString _root.errorString = _missionItem.areaData.errorString
} else { } else {
_root.errorString = "" _root.errorString = ""
}
} }
} }
}
Settings { Settings {
property alias showHint: hintHeader.checked property alias showHint: hintHeader.checked
} }
} } // GridLayout
} // Rectangle
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2 import QtQuick.Layouts 1.2
import QGroundControl 1.0 import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0 import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0 import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0 import QGroundControl.FlightMap 1.0
GridLayout { GridLayout {
id: editorColumn id: editorColumn
columns: 2 columns: 2
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
width: availableWidth width: availableWidth
property var geoArea: undefined property var geoArea: undefined
property int availableWidth property int availableWidth
...@@ -23,17 +23,18 @@ GridLayout { ...@@ -23,17 +23,18 @@ GridLayout {
property real _margin: ScreenTools.defaultFontPixelWidth / 2 property real _margin: ScreenTools.defaultFontPixelWidth / 2
Component.onCompleted: { Component.onCompleted: {
console.assert(geoArea !== undefined, "please set the areaItem property") console.assert(geoArea !== undefined,
"please set the areaItem property")
} }
SectionHeader { SectionHeader {
id: tilesHeader id: tilesHeader
text: qsTr("Tiles") text: qsTr("Tiles")
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
} }
GridLayout{ GridLayout {
visible: tilesHeader.checked visible: tilesHeader.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
...@@ -43,12 +44,12 @@ GridLayout { ...@@ -43,12 +44,12 @@ GridLayout {
QGCLabel { QGCLabel {
text: qsTr("Height") text: qsTr("Height")
Layout.fillWidth: true Layout.fillWidth: true
} }
FactTextField { FactTextField {
fact: geoArea.tileHeight fact: geoArea.tileHeight
Layout.fillWidth: true Layout.fillWidth: true
} }
QGCLabel { QGCLabel {
...@@ -57,36 +58,34 @@ GridLayout { ...@@ -57,36 +58,34 @@ GridLayout {
} }
FactTextField { FactTextField {
fact: geoArea.tileWidth fact: geoArea.tileWidth
Layout.fillWidth: true Layout.fillWidth: true
} }
QGCLabel { QGCLabel {
text: qsTr("Min. Area") text: qsTr("Min. Area")
Layout.fillWidth: true Layout.fillWidth: true
} }
FactTextField { FactTextField {
fact: geoArea.minTileArea fact: geoArea.minTileArea
Layout.fillWidth: true Layout.fillWidth: true
} }
FactCheckBox { FactCheckBox {
text: qsTr("Show Tiles") text: qsTr("Show Tiles")
fact: geoArea.showTiles fact: geoArea.showTiles
} }
} }
SectionHeader { SectionHeader {
id: statsHeader id: statsHeader
text: qsTr("Statistics") text: qsTr("Statistics")
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
} }
GridLayout{ GridLayout {
visible: statsHeader.checked visible: statsHeader.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
...@@ -94,14 +93,27 @@ GridLayout { ...@@ -94,14 +93,27 @@ GridLayout {
rowSpacing: _margin rowSpacing: _margin
columns: 2 columns: 2
QGCLabel { text: qsTr("Area") } QGCLabel {
// QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(geoArea.area).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString } text: qsTr("Area")
}
QGCLabel {
text: QGroundControl.unitsConversion.squareMetersToAppSettingsAreaUnits(
geoArea.area).toFixed(
2) + " " + QGroundControl.unitsConversion.appSettingsAreaUnitsString
}
QGCLabel { text: qsTr("Tiles") } QGCLabel {
QGCLabel { text: geoArea.tiles.count } text: qsTr("Tiles")
}
QGCLabel {
text: geoArea.tiles.count
}
QGCLabel { text: qsTr("Max. Tiles") } QGCLabel {
QGCLabel { text: geoArea.maxTiles } text: qsTr("Max. Tiles")
}
QGCLabel {
text: geoArea.maxTiles
}
} }
} // Column } // Column
...@@ -53,7 +53,7 @@ Rectangle { ...@@ -53,7 +53,7 @@ Rectangle {
readonly property int areaEditorIndex: 0 readonly property int areaEditorIndex: 0
readonly property int parameterEditorIndex: 1 readonly property int parameterEditorIndex: 1
readonly property int nemoControlsIndex: 2 readonly property int nemoEditorIndex: 2
property bool editing: _missionItem.editing property bool editing: _missionItem.editing
property bool correct: false property bool correct: false
...@@ -102,36 +102,35 @@ Rectangle { ...@@ -102,36 +102,35 @@ Rectangle {
} }
} }
StackLayout { MCI.AreaDataEditor {
width: parent.width id: areaEditor
currentIndex: tabBar.currentIndex
visible: tabBar.currentIndex === tabBar.areaEditorIndex
MCI.AreaDataEditor { checked: visible
id: areaEditor missionItem: _root._missionItem
checked: visible availableWidth: mainColumn.width
missionItem: _root._missionItem onAbort: {
availableWidth: parent.width missionItem.abortEditing()
onAbort: { tabBar.currentIndex = tabBar.parameterEditorIndex
missionItem.abortEditing()
tabBar.currentIndex = tabBar.parameterEditorIndex
}
} }
}
MCI.ParameterEditor { MCI.ParameterEditor {
id: parameterEditor id: parameterEditor
checked: visible visible: tabBar.currentIndex === tabBar.parameterEditorIndex
missionItem: _root._missionItem checked: visible
availableWidth: mainColumn.width missionItem: _root._missionItem
} availableWidth: mainColumn.width
}
MCI.NemoEditor { MCI.NemoEditor {
id: nemoEditor id: nemoEditor
checked: visible visible: tabBar.currentIndex === tabBar.nemoEditorIndex
missionItem: _root._missionItem checked: visible
availableWidth: mainColumn.width missionItem: _root._missionItem
} availableWidth: mainColumn.width
} }
} // main Column } // main Column
} // Rectangle } // Rectangle
import QtQuick 2.0 import QtQuick 2.0
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
import QtQuick.Layouts 1.11 import QtQuick.Layouts 1.11
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0 import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import MeasurementComplexItem 1.0 as MCI import MeasurementComplexItem 1.0 as MCI
GridLayout { Rectangle {
id: _root id: _root
width: mainGrid.width
height: mainGrid.height
color: qgcPal.windowShadeDark
property bool checked: true property bool checked: true
property var missionItem: undefined property var missionItem: undefined
property int availableWidth: 300 property int availableWidth: 300
...@@ -26,10 +31,6 @@ GridLayout { ...@@ -26,10 +31,6 @@ GridLayout {
property var _nemoInterface: MCI.NemoInterface property var _nemoInterface: MCI.NemoInterface
property bool _holding property bool _holding
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Component.onCompleted: { Component.onCompleted: {
console.assert(missionItem !== undefined, console.assert(missionItem !== undefined,
"please set the missionItem property") "please set the missionItem property")
...@@ -37,145 +38,154 @@ GridLayout { ...@@ -37,145 +38,154 @@ GridLayout {
_stopHolding() _stopHolding()
} }
QGCLabel {
text: _root.errorString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
Layout.fillWidth: true
visible: !_root.areasCorrect
}
QGCButton {
text: running ? qsTr("Stop") : qsTr("Start")
Layout.columnSpan: parent.columns
Layout.fillWidth: true
onPressed: {
if (running) {
_nemoInterface.stop()
} else {
_nemoInterface.start()
}
}
}
QGCLabel {
text: qsTr("Status: ") + _nemoInterface.statusString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignVCenter
Layout.columnSpan: parent.columns
Layout.fillWidth: true
}
SectionHeader {
id: progressHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
text: qsTr("Progress")
}
GridLayout { GridLayout {
id: mainGrid
width: availableWidth
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
columns: 2 columns: 2
Layout.columnSpan: parent.columns
Layout.fillWidth: true
visible: progressHeader.checked
QGCButton { QGCLabel {
text: !_holding ? qsTr("Hold") : qsTr("Stop Holding") text: _root.errorString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
Layout.fillWidth: true Layout.fillWidth: true
visible: !_root.areasCorrect
}
QGCButton {
text: running ? qsTr("Stop") : qsTr("Start")
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
Layout.fillWidth: true
onPressed: { onPressed: {
if (_holding) { if (running) {
_stopHolding() _nemoInterface.stop()
_holding = false
} else { } else {
_holdProgress() _nemoInterface.start()
_holding = true
} }
} }
} }
QGCButton { QGCLabel {
text: qsTr("Random") text: qsTr("Status: ") + _nemoInterface.statusString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignVCenter
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
Layout.fillWidth: true Layout.fillWidth: true
onPressed: {
_randomProgress()
}
} }
QGCButton { SectionHeader {
text: qsTr("Reset") id: progressHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
text: qsTr("Progress")
}
GridLayout {
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
Layout.fillWidth: true Layout.fillWidth: true
onPressed: { visible: progressHeader.checked
_resetProgress()
QGCButton {
text: !_holding ? qsTr("Hold") : qsTr("Stop Holding")
Layout.fillWidth: true
Layout.columnSpan: parent.columns
onPressed: {
if (_holding) {
_stopHolding()
_holding = false
} else {
_holdProgress()
_holding = true
}
}
}
QGCButton {
text: qsTr("Random")
Layout.columnSpan: parent.columns
Layout.fillWidth: true
onPressed: {
_randomProgress()
}
}
QGCButton {
text: qsTr("Reset")
Layout.columnSpan: parent.columns
Layout.fillWidth: true
onPressed: {
_resetProgress()
}
} }
} }
}
// bussy indicator // bussy indicator
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: _margin spacing: _margin
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
BusyIndicator { BusyIndicator {
id: indicator id: indicator
property bool calculating: missionItem.calculating property bool calculating: missionItem.calculating
running: calculating running: calculating
visible: calculating || timer.running visible: calculating || timer.running
onCalculatingChanged: { onCalculatingChanged: {
if (!calculating) { if (!calculating) {
// defer hiding // defer hiding
timer.restart() timer.restart()
}
} }
}
Timer { Timer {
id: timer id: timer
interval: 1000 interval: 1000
repeat: false repeat: false
running: false running: false
}
} }
} } // indicator column
} // indicator column
SectionHeader { SectionHeader {
id: hintHeader id: hintHeader
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
text: qsTr("Hints") text: qsTr("Hints")
} }
GridLayout { GridLayout {
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
columns: 2 columns: 2
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
visible: hintHeader.checked visible: hintHeader.checked
QGCLabel { QGCLabel {
id: hintLabel id: hintLabel
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
text: qsTr("Use this tab to connect to a device implementing the Nemo Interface. text: qsTr("Use this tab to connect to a device implementing the Nemo Interface.
Use the Random button to simulate measurement progress.") Use the Random button to simulate measurement progress.")
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
}
} }
}
Settings { Settings {
property alias showHint: hintHeader.checked property alias showHint: hintHeader.checked
} }
} // GridLayout
function _holdProgress() { function _holdProgress() {
var areaArray = _areaData.measurementAreaList var areaArray = _areaData.measurementAreaList
...@@ -224,4 +234,4 @@ Use the Random button to simulate measurement progress.") ...@@ -224,4 +234,4 @@ Use the Random button to simulate measurement progress.")
} }
} }
} }
} } // Rectangle
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.4 import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2 import QtQuick.Layouts 1.2
import QGroundControl 1.0 import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0 import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0 import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0 import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0 import QGroundControl.FlightMap 1.0
GridLayout { Rectangle {
id:_root id: _root
width: mainGrid.width
height: mainGrid.height
color: qgcPal.windowShadeDark
property bool checked: true property bool checked: true
property var missionItem: undefined property var missionItem: undefined
property int availableWidth: 300 property int availableWidth: 300
property real _margin: ScreenTools.defaultFontPixelWidth / 2 property real _margin: ScreenTools.defaultFontPixelWidth / 2
property var _generator: missionItem.generator property var _generator: missionItem.generator
property var _generatorEditor: undefined property var _generatorEditor: undefined
width: availableWidth
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Component.onCompleted: { Component.onCompleted: {
console.assert(missionItem !== undefined, "please set the missionItem property") console.assert(missionItem !== undefined,
"please set the missionItem property")
_addGeneratorEditor() _addGeneratorEditor()
} }
...@@ -44,183 +44,190 @@ GridLayout { ...@@ -44,183 +44,190 @@ GridLayout {
_addGeneratorEditor() _addGeneratorEditor()
} }
GridLayout {
id: mainGrid
columnSpacing: _margin
rowSpacing: _margin
columns: 2
width: availableWidth
SectionHeader { SectionHeader {
id: generalHeader id: generalHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
Layout.maximumWidth: parent.width
text: qsTr("General")
}
GridLayout {
id: generalGrid
Layout.fillWidth: true
Layout.columnSpan: parent.columns
Layout.maximumWidth: parent.width
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: generalHeader.checked
QGCLabel {
text: qsTr("Altitude")
Layout.fillWidth: true Layout.fillWidth: true
}
FactTextField {
fact: missionItem.altitude
Layout.fillWidth: true
}
QGCLabel {
text: qsTr("Variant")
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
visible: variantRepeater.len > 0 Layout.maximumWidth: parent.width
text: qsTr("General")
} }
ExclusiveGroup{id:variantGroup} GridLayout {
id: generalGrid
GridLayout{ Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
columns: 3 columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: generalHeader.checked
QGCLabel {
text: qsTr("Altitude")
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.altitude
Layout.fillWidth: true
}
QGCLabel {
text: qsTr("Variant")
Layout.columnSpan: parent.columns
visible: variantRepeater.len > 0
}
ExclusiveGroup {
id: variantGroup
}
columnSpacing: _margin GridLayout {
rowSpacing: _margin Layout.columnSpan: parent.columns
Layout.maximumWidth: parent.width
columns: 3
Repeater{ columnSpacing: _margin
id: variantRepeater rowSpacing: _margin
property var names: missionItem.variantNames Repeater {
property int len: missionItem.variantNames.length id: variantRepeater
model: len property var names: missionItem.variantNames
delegate: QGCRadioButton { property int len: missionItem.variantNames.length
checked: index === variantIndex
text: variantRepeater.names[index] ? variantRepeater.names[index]: ""
Layout.fillWidth: true
property int variantIndex: missionItem.variantIndex.value model: len
delegate: QGCRadioButton {
checked: index === variantIndex
text: variantRepeater.names[index] ? variantRepeater.names[index] : ""
Layout.fillWidth: true
onVariantIndexChanged: { property int variantIndex: missionItem.variantIndex.value
if (variantIndex === index){
checked = true onVariantIndexChanged: {
if (variantIndex === index) {
checked = true
}
} }
}
onCheckedChanged: { onCheckedChanged: {
if (checked && variantIndex !== index){ if (checked && variantIndex !== index) {
missionItem.variantIndex.value = index missionItem.variantIndex.value = index
}
} }
} }
} } // variant repeater
} // variant repeater } // variant grid
} // variant grid } // general grid
} // general grid
// Generator Editor
SectionHeader {
id: generatorHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
text: qsTr("Generator")
}
GridLayout{ // Generator Editor
Layout.fillWidth: true SectionHeader {
columnSpacing: _margin id: generatorHeader
Layout.maximumWidth: parent.width Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
rowSpacing: _margin text: qsTr("Generator")
columns: 2 }
visible: generatorHeader.checked
GridLayout {
QGCComboBox { Layout.fillWidth: true
property var names: missionItem.generatorNameList columnSpacing: _margin
property int length: names.length Layout.maximumWidth: parent.width
Layout.columnSpan: parent.columns
enabled: _root.checked rowSpacing: _margin
anchors.margins: ScreenTools.defaultFontPixelWidth columns: 2
currentIndex: missionItem.generatorIndex visible: generatorHeader.checked
Layout.columnSpan: 2
model: missionItem.generatorNameList QGCComboBox {
property var names: missionItem.generatorNameList
onActivated: { property int length: names.length
if (index != -1){
missionItem.switchToGenerator(index) enabled: _root.checked
anchors.margins: ScreenTools.defaultFontPixelWidth
currentIndex: missionItem.generatorIndex
Layout.columnSpan: 2
model: missionItem.generatorNameList
onActivated: {
if (index != -1) {
missionItem.switchToGenerator(index)
}
} }
} }
} }
}
ColumnLayout{ ColumnLayout {
id:generatorEditorParent id: generatorEditorParent
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
visible: generatorHeader.checked visible: generatorHeader.checked
} }
QGCButton{ QGCButton {
text:qsTr("Reverse") text: qsTr("Reverse")
onClicked: missionItem.reverseRoute() onClicked: missionItem.reverseRoute()
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
} }
// bussy indicator // bussy indicator
ColumnLayout{ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: _margin spacing: _margin
Layout.maximumWidth: parent.width Layout.maximumWidth: parent.width
BusyIndicator{ BusyIndicator {
id: indicator id: indicator
property bool calculating: missionItem.calculating property bool calculating: missionItem.calculating
running: calculating running: calculating
visible: calculating || timer.running visible: calculating || timer.running
onCalculatingChanged: { onCalculatingChanged: {
if(!calculating){ if (!calculating) {
// defer hiding // defer hiding
timer.restart() timer.restart()
}
} }
}
Timer{ Timer {
id: timer id: timer
interval: 1000 interval: 1000
repeat: false repeat: false
running: false running: false
}
} }
} } // indicator column
} // indicator column } // GridLayout
function _addGeneratorEditor(){ function _addGeneratorEditor() {
if (_generator && _generator.editorQml && !_generatorEditor) { if (_generator && _generator.editorQml && !_generatorEditor) {
var component = Qt.createComponent(_generator.editorQml) var component = Qt.createComponent(_generator.editorQml)
if (component.status === Component.Error) { if (component.status === Component.Error) {
console.log("Error loading Qml: ", console.log("Error loading Qml: ", _generator.editorQml,
_generator.editorQml, component.errorString()) component.errorString())
} else { } else {
_generatorEditor = _generatorEditor = component.createObject(
component.createObject(
generatorEditorParent, { generatorEditorParent, {
"generator": _root._generator, "generator": _root._generator,
"availableWidth": generatorEditorParent.width, "availableWidth": generatorEditorParent.width
}) })
} }
} }
} }
function _destroyGeneratorEditor(){ function _destroyGeneratorEditor() {
if (_generatorEditor){ if (_generatorEditor) {
_generatorEditor.destroy() _generatorEditor.destroy()
_generatorEditor = undefined _generatorEditor = undefined
} }
} }
} } // Rectangle
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2 import QtQuick.Layouts 1.2
import QGroundControl 1.0 import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0 import QGroundControl.FactControls 1.0
GridLayout { GridLayout {
id: editorColumn id: editorColumn
columns: 2 columns: 2
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
width: availableWidth width: availableWidth
property var geoArea: undefined property var geoArea: undefined
property int availableWidth property int availableWidth
...@@ -20,12 +20,13 @@ GridLayout { ...@@ -20,12 +20,13 @@ GridLayout {
property real _margin: ScreenTools.defaultFontPixelWidth / 2 property real _margin: ScreenTools.defaultFontPixelWidth / 2
Component.onCompleted: { Component.onCompleted: {
console.assert(geoArea !== undefined, "please set the areaItem property") console.assert(geoArea !== undefined,
"please set the areaItem property")
} }
SectionHeader { SectionHeader {
id: statsHeader id: statsHeader
text: qsTr("Statistics") text: qsTr("Statistics")
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
} }
...@@ -34,11 +35,17 @@ GridLayout { ...@@ -34,11 +35,17 @@ GridLayout {
columns: 2 columns: 2
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
visible: statsHeader.checked visible: statsHeader.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
QGCLabel { text: qsTr("Area") } QGCLabel {
//QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(geoArea.area).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString } text: qsTr("Area")
}
QGCLabel {
text: QGroundControl.unitsConversion.squareMetersToAppSettingsAreaUnits(
geoArea.area).toFixed(
2) + " " + QGroundControl.unitsConversion.appSettingsAreaUnitsString
}
} }
} }
#include "QmlObjectVectorModel.h"
#include <QDebug>
#include <QQmlEngine>
const int QmlObjectVectorModel::ObjectRole = Qt::UserRole;
const int QmlObjectVectorModel::TextRole = Qt::UserRole + 1;
QmlObjectVectorModel::QmlObjectVectorModel(QObject* parent)
: QAbstractListModel(parent)
, _dirty(false)
, _skipDirtyFirstItem(false)
{
}
int QmlObjectVectorModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return _objectList.count();
}
QVariant QmlObjectVectorModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
if (index.row() < 0 || index.row() >= _objectList.count()) {
return QVariant();
}
if (role == ObjectRole) {
return QVariant::fromValue(_objectList[index.row()]);
} else if (role == TextRole) {
return QVariant::fromValue(_objectList[index.row()]->objectName());
} else {
return QVariant();
}
}
QHash<int, QByteArray> QmlObjectVectorModel::roleNames(void) const
{
QHash<int, QByteArray> hash;
hash[ObjectRole] = "object";
hash[TextRole] = "text";
return hash;
}
bool QmlObjectVectorModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (index.isValid() && role == ObjectRole) {
_objectList.replace(index.row(), value.value<QObject*>());
emit dataChanged(index, index);
return true;
}
return false;
}
bool QmlObjectVectorModel::insertRows(int position, int rows, const QModelIndex& parent)
{
Q_UNUSED(parent);
if (position < 0 || position > _objectList.count() + 1) {
qWarning() << "Invalid position position:count" << position << _objectList.count();
}
beginInsertRows(QModelIndex(), position, position + rows - 1);
endInsertRows();
emit countChanged(count());
return true;
}
bool QmlObjectVectorModel::removeRows(int position, int rows, const QModelIndex& parent)
{
Q_UNUSED(parent);
if (position < 0 || position >= _objectList.count()) {
qWarning() << "Invalid position position:count" << position << _objectList.count();
} else if (position + rows > _objectList.count()) {
qWarning() << "Invalid rows position:rows:count" << position << rows << _objectList.count();
}
beginRemoveRows(QModelIndex(), position, position + rows - 1);
for (int row=0; row<rows; row++) {
_objectList.removeAt(position);
}
endRemoveRows();
emit countChanged(count());
return true;
}
QObject* QmlObjectVectorModel::operator[](int index)
{
if (index < 0 || index >= _objectList.count()) {
return NULL;
}
return _objectList[index];
}
const QObject* QmlObjectVectorModel::operator[](int index) const
{
if (index < 0 || index >= _objectList.count()) {
return NULL;
}
return _objectList[index];
}
void QmlObjectVectorModel::clear()
{
while (rowCount()) {
removeAt(0);
}
}
QObject* QmlObjectVectorModel::removeAt(int i)
{
QObject* removedObject = _objectList[i];
if(removedObject) {
// Look for a dirtyChanged signal on the object
if (_objectList[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
if (!_skipDirtyFirstItem || i != 0) {
QObject::disconnect(_objectList[i], SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
}
}
removeRows(i, 1);
setDirty(true);
return removedObject;
}
void QmlObjectVectorModel::insert(int i, QObject* object)
{
if (i < 0 || i > _objectList.count()) {
qWarning() << "Invalid index index:count" << i << _objectList.count();
}
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
// Look for a dirtyChanged signal on the object
if (object->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
if (!_skipDirtyFirstItem || i != 0) {
QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
}
_objectList.insert(i, object);
insertRows(i, 1);
setDirty(true);
}
void QmlObjectVectorModel::insert(int i, QVector<QObject*> objects)
{
if (i < 0 || i > _objectList.count()) {
qWarning() << "Invalid index index:count" << i << _objectList.count();
}
int j = i;
for (QObject* object: objects) {
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
// Look for a dirtyChanged signal on the object
if (object->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("dirtyChanged(bool)")) != -1) {
if (!_skipDirtyFirstItem || j != 0) {
QObject::connect(object, SIGNAL(dirtyChanged(bool)), this, SLOT(_childDirtyChanged(bool)));
}
}
j++;
_objectList.insert(j, object);
}
insertRows(i, objects.count());
setDirty(true);
}
void QmlObjectVectorModel::append(QObject* object)
{
insert(_objectList.count(), object);
}
void QmlObjectVectorModel::append(QVector<QObject*> objects)
{
insert(_objectList.count(), objects);
}
QVector<QObject*> QmlObjectVectorModel::swapObjectList(const QVector<QObject*>& newlist)
{
QVector<QObject*> oldlist(_objectList);
beginResetModel();
_objectList = newlist;
endResetModel();
emit countChanged(count());
return oldlist;
}
int QmlObjectVectorModel::count() const
{
return rowCount();
}
void QmlObjectVectorModel::setDirty(bool dirty)
{
if (_dirty != dirty) {
_dirty = dirty;
if (!dirty) {
// Need to clear dirty from all children
for(QObject* object: _objectList) {
if (object->property("dirty").isValid()) {
object->setProperty("dirty", false);
}
}
}
emit dirtyChanged(_dirty);
}
}
void QmlObjectVectorModel::_childDirtyChanged(bool dirty)
{
_dirty |= dirty;
// We want to emit dirtyChanged even if the actual value of _dirty didn't change. It can be a useful
// signal to know when a child has changed dirty state
emit dirtyChanged(_dirty);
}
void QmlObjectVectorModel::deleteListAndContents()
{
for (int i=0; i<_objectList.count(); i++) {
_objectList[i]->deleteLater();
}
deleteLater();
}
void QmlObjectVectorModel::clearAndDeleteContents()
{
beginResetModel();
for (int i=0; i<_objectList.count(); i++) {
_objectList[i]->deleteLater();
}
clear();
endResetModel();
}
void swap(QmlObjectVectorModel &list1, QmlObjectVectorModel &list2)
{
using std::swap;
swap(list1._objectList, list2._objectList);
swap(list1._dirty, list2._dirty);
swap(list1._skipDirtyFirstItem, list2._skipDirtyFirstItem);
}
#pragma once
#include <QAbstractListModel>
class QmlObjectVectorModel : public QAbstractListModel
{
Q_OBJECT
public:
QmlObjectVectorModel(QObject* parent = nullptr);
Q_PROPERTY(int count READ count NOTIFY countChanged)
/// Returns true if any of the items in the list are dirty. Requires each object to have
/// a dirty property and dirtyChanged signal.
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
Q_INVOKABLE QObject* get(int index) { return _objectList[index]; }
// Property accessors
int count () const;
bool dirty () const { return _dirty; }
void setDirty (bool dirty);
void append (QObject* object);
void append (QVector<QObject*> objects);
QVector<QObject*> swapObjectList (const QVector<QObject*>& newlist);
void clear ();
QObject* removeAt (int i);
QObject* removeOne (QObject* object) { return removeAt(indexOf(object)); }
void insert (int i, QObject* object);
void insert (int i, QVector<QObject*> objects);
bool contains (QObject* object) { return _objectList.indexOf(object) != -1; }
int indexOf (QObject* object) { return _objectList.indexOf(object); }
QObject* operator[] (int i);
const QObject* operator[] (int i) const;
template<class T> T value (int index) { return qobject_cast<T>(_objectList[index]); }
QVector<QObject*>* objectList () { return &_objectList; }
/// Calls deleteLater on all items and this itself.
void deleteListAndContents ();
/// Clears the list and calls deleteLater on each entry
void clearAndDeleteContents ();
void beginReset () { beginResetModel(); }
void endReset () { endResetModel(); }
// Friends
friend void swap(QmlObjectVectorModel& list1, QmlObjectVectorModel& list2);
signals:
void countChanged (int count);
void dirtyChanged (bool dirtyChanged);
private slots:
void _childDirtyChanged (bool dirty);
private:
// Overrides from QAbstractListModel
int rowCount (const QModelIndex & parent = QModelIndex()) const override;
QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override;
bool insertRows (int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows (int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
QHash<int, QByteArray> roleNames(void) const override;
private:
QVector<QObject*> _objectList;
bool _dirty;
bool _skipDirtyFirstItem;
static const int ObjectRole;
static const int TextRole;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment