Browse Source

Merge pull request #8726 from DonLakeFlyer/QGCPipOverlay

More FlyView encasulation. Make QGCPipOverlay completely self contained
QGC4.4
Don Gagne 5 years ago committed by GitHub
parent
commit
2c09c1d868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      qgroundcontrol.qrc
  2. 279
      src/FlightDisplay/FlightDisplayView.qml
  3. 24
      src/FlightDisplay/FlightDisplayViewMap.qml
  4. 5
      src/FlightDisplay/FlightDisplayViewVideo.qml
  5. 5
      src/FlightDisplay/FlightDisplayViewWidgets.qml
  6. 2
      src/FlightMap/Widgets/QGCInstrumentWidget.qml
  7. 25
      src/QmlControls/QGCControlDebug.qml
  8. 243
      src/QmlControls/QGCPipOverlay.qml
  9. 96
      src/QmlControls/QGCPipState.qml
  10. 191
      src/QmlControls/QGCPipable.qml
  11. 4
      src/QmlControls/QGroundControl/Controls/qmldir
  12. 1
      src/ui/MainRootWindow.qml

4
qgroundcontrol.qrc

@ -127,6 +127,7 @@
<file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file> <file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file>
<file alias="QGroundControl/Controls/QGCCheckBox.qml">src/QmlControls/QGCCheckBox.qml</file> <file alias="QGroundControl/Controls/QGCCheckBox.qml">src/QmlControls/QGCCheckBox.qml</file>
<file alias="QGroundControl/Controls/QGCColoredImage.qml">src/QmlControls/QGCColoredImage.qml</file> <file alias="QGroundControl/Controls/QGCColoredImage.qml">src/QmlControls/QGCColoredImage.qml</file>
<file alias="QGroundControl/Controls/QGCControlDebug.qml">src/QmlControls/QGCControlDebug.qml</file>
<file alias="QGroundControl/Controls/QGCComboBox.qml">src/QmlControls/QGCComboBox.qml</file> <file alias="QGroundControl/Controls/QGCComboBox.qml">src/QmlControls/QGCComboBox.qml</file>
<file alias="QGroundControl/Controls/QGCFileDialog.qml">src/QmlControls/QGCFileDialog.qml</file> <file alias="QGroundControl/Controls/QGCFileDialog.qml">src/QmlControls/QGCFileDialog.qml</file>
<file alias="QGroundControl/Controls/QGCFlickable.qml">src/QmlControls/QGCFlickable.qml</file> <file alias="QGroundControl/Controls/QGCFlickable.qml">src/QmlControls/QGCFlickable.qml</file>
@ -147,7 +148,8 @@
<file alias="QGroundControl/Controls/QGCMovableItem.qml">src/QmlControls/QGCMovableItem.qml</file> <file alias="QGroundControl/Controls/QGCMovableItem.qml">src/QmlControls/QGCMovableItem.qml</file>
<file alias="QGroundControl/Controls/QGCPopupDialog.qml">src/QmlControls/QGCPopupDialog.qml</file> <file alias="QGroundControl/Controls/QGCPopupDialog.qml">src/QmlControls/QGCPopupDialog.qml</file>
<file alias="QGroundControl/Controls/QGCPopupDialogContainer.qml">src/QmlControls/QGCPopupDialogContainer.qml</file> <file alias="QGroundControl/Controls/QGCPopupDialogContainer.qml">src/QmlControls/QGCPopupDialogContainer.qml</file>
<file alias="QGroundControl/Controls/QGCPipable.qml">src/QmlControls/QGCPipable.qml</file> <file alias="QGroundControl/Controls/QGCPipOverlay.qml">src/QmlControls/QGCPipOverlay.qml</file>
<file alias="QGroundControl/Controls/QGCPipState.qml">src/QmlControls/QGCPipState.qml</file>
<file alias="QGroundControl/Controls/QGCRadioButton.qml">src/QmlControls/QGCRadioButton.qml</file> <file alias="QGroundControl/Controls/QGCRadioButton.qml">src/QmlControls/QGCRadioButton.qml</file>
<file alias="QGroundControl/Controls/QGCSlider.qml">src/QmlControls/QGCSlider.qml</file> <file alias="QGroundControl/Controls/QGCSlider.qml">src/QmlControls/QGCSlider.qml</file>
<file alias="QGroundControl/Controls/QGCSwitch.qml">src/QmlControls/QGCSwitch.qml</file> <file alias="QGroundControl/Controls/QGCSwitch.qml">src/QmlControls/QGCSwitch.qml</file>

279
src/FlightDisplay/FlightDisplayView.qml

@ -39,40 +39,20 @@ Item {
} }
} }
property bool mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true property bool _mainWindowIsMap: mapControl.pipState.state === mapControl.pipState.fullState
property bool isBackgroundDark: mainIsMap ? (mainWindow.flightDisplayMap ? mainWindow.flightDisplayMap.isSatelliteMap : true) : true property bool _isMapDark: _mainWindowIsMap ? mapControl.isSatelliteMap : true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _missionController: _planController.missionController property var _missionController: _planController.missionController
property var _geoFenceController: _planController.geoFenceController property var _geoFenceController: _planController.geoFenceController
property var _rallyPointController: _planController.rallyPointController property var _rallyPointController: _planController.rallyPointController
property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
property real _margins: ScreenTools.defaultFontPixelWidth / 2 property real _margins: ScreenTools.defaultFontPixelWidth / 2
property real _pipSize: mainWindow.width * 0.2
property alias _guidedController: guidedActionsController property alias _guidedController: guidedActionsController
property alias _guidedConfirm: guidedActionConfirm property alias _guidedConfirm: guidedActionConfirm
property alias _guidedList: guidedActionList property alias _guidedList: guidedActionList
property alias _guidedSlider: altitudeSlider property alias _guidedSlider: altitudeSlider
property real _guidedZOrder: _flightVideoPipControl.z + 1
property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75 property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75
readonly property string _mapName: "FlightDisplayView" readonly property string _mapName: "FlightDisplayView"
readonly property string _showMapBackgroundKey: "/showMapBackground"
readonly property string _mainIsMapKey: "MainFlyWindowIsMap"
readonly property string _PIPVisibleKey: "IsPIPVisible"
function setStates() {
QGroundControl.saveBoolGlobalSetting(_mainIsMapKey, mainIsMap)
if(mainIsMap) {
//-- Adjust Margins
_flightMapContainer.state = "fullMode"
_flightVideo.state = "pipMode"
} else {
//-- Adjust Margins
_flightMapContainer.state = "pipMode"
_flightVideo.state = "fullMode"
}
}
function setPipVisibility(state) { function setPipVisibility(state) {
_isPipVisible = state; _isPipVisible = state;
@ -93,12 +73,6 @@ Item {
return true; return true;
} }
// Signal routing
Connections {
target: mainWindow
onFlightDisplayMapChanged: setStates()
}
Component.onCompleted: { Component.onCompleted: {
if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) { if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) {
flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay
@ -112,180 +86,66 @@ Item {
guidedController: _guidedController guidedController: _guidedController
} }
Window { QGCMapPalette { id: mapPal; lightColors: _mainWindowIsMap ? mapControl.isSatelliteMap : true }
id: videoWindow
width: !mainIsMap ? _mapAndVideo.width : _pipSize
height: !mainIsMap ? _mapAndVideo.height : _pipSize * (9/16)
visible: false
Item {
id: videoItem
anchors.fill: parent
}
onClosing: {
_flightVideo.state = "unpopup"
videoWindow.visible = false
}
}
/* This timer will startVideo again after the popup window appears and is loaded.
* Such approach was the only one to avoid a crash for windows users
*/
Timer {
id: videoPopUpTimer
interval: 2000;
running: false;
repeat: false
onTriggered: {
// If state is popup, the next one will be popup-finished
if (_flightVideo.state == "popup") {
_flightVideo.state = "popup-finished"
}
QGroundControl.videoManager.startVideo()
}
}
QGCMapPalette { id: mapPal; lightColors: mainIsMap ? mainWindow.flightDisplayMap.isSatelliteMap : true }
Item { Item {
id: _mapAndVideo id: _mapAndVideo
anchors.fill: parent anchors.fill: parent
//-- Map View
Item {
id: _flightMapContainer
z: mainIsMap ? _mapAndVideo.z + 1 : _mapAndVideo.z + 2
anchors.left: _mapAndVideo.left
anchors.bottom: _mapAndVideo.bottom
visible: mainIsMap || _isPipVisible && !QGroundControl.videoManager.fullScreen
width: mainIsMap ? _mapAndVideo.width : _pipSize
height: mainIsMap ? _mapAndVideo.height : _pipSize * (9/16)
states: [
State {
name: "pipMode"
PropertyChanges {
target: _flightMapContainer
anchors.margins: ScreenTools.defaultFontPixelHeight
}
},
State {
name: "fullMode"
PropertyChanges {
target: _flightMapContainer
anchors.margins: 0
}
}
]
FlightDisplayViewMap { FlightDisplayViewMap {
id: _fMap id: mapControl
anchors.fill: parent
guidedActionsController: _guidedController guidedActionsController: _guidedController
planMasterController: _planController planMasterController: _planController
flightWidgets: flightDisplayViewWidgets flightWidgets: flightDisplayViewWidgets
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9 rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9
scaleState: (mainIsMap && flyViewOverlay.item) ? (flyViewOverlay.item.scaleState ? flyViewOverlay.item.scaleState : "bottomMode") : "bottomMode" scaleState: (_mainWindowIsMap && flyViewOverlay.item) ? (flyViewOverlay.item.scaleState ? flyViewOverlay.item.scaleState : "bottomMode") : "bottomMode"
Component.onCompleted: { mainWindowIsMap: _mainWindowIsMap
mainWindow.flightDisplayMap = _fMap
_fMap.adjustMapSize() property var pipState: mapPipState
} QGCPipState {
id: mapPipState
pipOverlay: _pipOverlay
isDark: _isMapDark
} }
} }
//-- Video View //-- Video View
Item { Item {
id: _flightVideo id: videoControl
z: mainIsMap ? _mapAndVideo.z + 2 : _mapAndVideo.z + 1 visible: QGroundControl.videoManager.hasVideo
width: !mainIsMap ? _mapAndVideo.width : _pipSize
height: !mainIsMap ? _mapAndVideo.height : _pipSize * (9/16) property var pipState: videoPipState
anchors.left: _mapAndVideo.left QGCPipState {
anchors.bottom: _mapAndVideo.bottom id: videoPipState
visible: QGroundControl.videoManager.hasVideo && (!mainIsMap || _isPipVisible) pipOverlay: _pipOverlay
isDark: true
onParentChanged: {
/* If video comes back from popup onWindowAboutToOpen: {
* correct anchors. console.log("about to open")
* Such thing is not possible with ParentChange.
*/
if(parent == _mapAndVideo) {
// Do anchors again after popup
anchors.left = _mapAndVideo.left
anchors.bottom = _mapAndVideo.bottom
anchors.margins = _toolsMargin
}
}
states: [
State {
name: "pipMode"
PropertyChanges {
target: _flightVideo
anchors.margins: ScreenTools.defaultFontPixelHeight
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: false
}
},
State {
name: "fullMode"
PropertyChanges {
target: _flightVideo
anchors.margins: 0
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: false
}
},
State {
name: "popup"
StateChangeScript {
script: {
// Stop video, restart it again with Timer
// Avoiding crashes if ParentChange is not yet done
QGroundControl.videoManager.stopVideo()
videoPopUpTimer.running = true
}
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: true
}
},
State {
name: "popup-finished"
ParentChange {
target: _flightVideo
parent: videoItem
x: 0
y: 0
width: videoItem.width
height: videoItem.height
}
},
State {
name: "unpopup"
StateChangeScript {
script: {
QGroundControl.videoManager.stopVideo() QGroundControl.videoManager.stopVideo()
videoPopUpTimer.running = true videoStartDelay.start()
}
} }
ParentChange {
target: _flightVideo onWindowAboutToClose: {
parent: _mapAndVideo console.log("about to close")
QGroundControl.videoManager.stopVideo()
videoStartDelay.start()
} }
PropertyChanges {
target: _flightVideoPipControl
inPopup: false
} }
Timer {
id: videoStartDelay
interval: 2000;
running: false
repeat: false
onTriggered: QGroundControl.videoManager.startVideo()
} }
]
//-- Video Streaming //-- Video Streaming
FlightDisplayViewVideo { FlightDisplayViewVideo {
id: videoStreaming id: videoStreaming
anchors.fill: parent anchors.fill: parent
useSmallFont: videoControl.pipState.state !== videoControl.pipState.fullState
visible: QGroundControl.videoManager.isGStreamer visible: QGroundControl.videoManager.isGStreamer
} }
//-- UVC Video (USB Camera or Video Device) //-- UVC Video (USB Camera or Video Device)
@ -297,33 +157,16 @@ Item {
} }
} }
QGCPipable { QGCPipOverlay {
id: _flightVideoPipControl id: _pipOverlay
z: _flightVideo.z + 3 anchors.left: parent.left
width: _pipSize anchors.bottom: parent.bottom
height: _pipSize * (9/16)
anchors.left: _mapAndVideo.left
anchors.bottom: _mapAndVideo.bottom
anchors.margins: ScreenTools.defaultFontPixelHeight anchors.margins: ScreenTools.defaultFontPixelHeight
visible: QGroundControl.videoManager.hasVideo && !QGroundControl.videoManager.fullScreen && _flightVideo.state != "popup" item1IsFullSettingsKey: "MainFlyWindowIsMap"
isHidden: !_isPipVisible item1: mapControl
isDark: isBackgroundDark item2: QGroundControl.videoManager.hasVideo ? videoControl : null
enablePopup: mainIsMap fullZOrder: 0
onActivated: { pipZOrder: QGroundControl.zOrderWidgets
mainIsMap = !mainIsMap
setStates()
_fMap.adjustMapSize()
}
onHideIt: {
setPipVisibility(!state)
}
onPopup: {
videoWindow.visible = true
_flightVideo.state = "popup"
}
onNewWidth: {
_pipSize = newWidth
}
} }
MultiVehiclePanel { MultiVehiclePanel {
@ -331,20 +174,20 @@ Item {
anchors.margins: _toolsMargin anchors.margins: _toolsMargin
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
z: _mapAndVideo.z + 4 z: QGroundControl.zOrderWidgets
availableHeight: mainWindow.availableHeight - (anchors.margins * 2) availableHeight: mainWindow.availableHeight - (anchors.margins * 2)
guidedActionsController: _guidedController guidedActionsController: _guidedController
} }
FlightDisplayViewWidgets { FlightDisplayViewWidgets {
id: flightDisplayViewWidgets id: flightDisplayViewWidgets
z: _mapAndVideo.z + 4 z: QGroundControl.zOrderWidgets
height: availableHeight - (singleMultiSelector.visible ? singleMultiSelector.height + _toolsMargin : 0) - _toolsMargin height: availableHeight - (singleMultiSelector.visible ? singleMultiSelector.height + _toolsMargin : 0) - _toolsMargin
anchors.left: parent.left anchors.left: parent.left
anchors.right: altitudeSlider.visible ? altitudeSlider.left : parent.right anchors.right: altitudeSlider.visible ? altitudeSlider.left : parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: singleMultiSelector.visible? singleMultiSelector.bottom : undefined anchors.top: singleMultiSelector.visible? singleMultiSelector.bottom : undefined
useLightColors: isBackgroundDark useLightColors: _isMapDark
missionController: _missionController missionController: _missionController
visible: singleMultiSelector.singleVehiclePanel && !QGroundControl.videoManager.fullScreen visible: singleMultiSelector.singleVehiclePanel && !QGroundControl.videoManager.fullScreen
} }
@ -353,7 +196,7 @@ Item {
//-- Loader helper for plugins to overlay elements over the fly view //-- Loader helper for plugins to overlay elements over the fly view
Loader { Loader {
id: flyViewOverlay id: flyViewOverlay
z: flightDisplayViewWidgets.z + 1 z: QGroundControl.zOrderWidgets
visible: !QGroundControl.videoManager.fullScreen visible: !QGroundControl.videoManager.fullScreen
height: mainWindow.height - mainWindow.header.height height: mainWindow.height - mainWindow.header.height
anchors.left: parent.left anchors.left: parent.left
@ -364,17 +207,17 @@ Item {
//-- Virtual Joystick //-- Virtual Joystick
Loader { Loader {
id: virtualJoystickMultiTouch id: virtualJoystickMultiTouch
z: _mapAndVideo.z + 5 z: QGroundControl.zOrderTopMost + 1
width: parent.width - (_flightVideoPipControl.width / 2) width: parent.width - (_pipOverlay.width / 2)
height: Math.min(mainWindow.height * 0.25, ScreenTools.defaultFontPixelWidth * 16) height: Math.min(mainWindow.height * 0.25, ScreenTools.defaultFontPixelWidth * 16)
visible: (_virtualJoystick ? _virtualJoystick.value : false) && !QGroundControl.videoManager.fullScreen && !(_activeVehicle ? _activeVehicle.highLatencyLink : false) visible: (_virtualJoystick ? _virtualJoystick.value : false) && !QGroundControl.videoManager.fullScreen && !(_activeVehicle ? _activeVehicle.highLatencyLink : false)
anchors.bottom: _flightVideoPipControl.top anchors.bottom: _pipOverlay.top
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 2 anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 2
anchors.horizontalCenter: flightDisplayViewWidgets.horizontalCenter anchors.horizontalCenter: flightDisplayViewWidgets.horizontalCenter
source: "qrc:/qml/VirtualJoystick.qml" source: "qrc:/qml/VirtualJoystick.qml"
active: (_virtualJoystick ? _virtualJoystick.value : false) && !(_activeVehicle ? _activeVehicle.highLatencyLink : false) active: (_virtualJoystick ? _virtualJoystick.value : false) && !(_activeVehicle ? _activeVehicle.highLatencyLink : false)
property bool useLightColors: isBackgroundDark property bool useLightColors: _isMapDark
// The default behaviour is not centralized throttle // The default behaviour is not centralized throttle
property bool centralizeThrottle: _virtualJoystickCentralized ? _virtualJoystickCentralized.value : false property bool centralizeThrottle: _virtualJoystickCentralized ? _virtualJoystickCentralized.value : false
@ -390,8 +233,8 @@ Item {
anchors.right: isInstrumentRight() ? undefined : _mapAndVideo.right anchors.right: isInstrumentRight() ? undefined : _mapAndVideo.right
anchors.topMargin: _toolsMargin anchors.topMargin: _toolsMargin
anchors.top: parent.top anchors.top: parent.top
z: _mapAndVideo.z + 4 z: QGroundControl.zOrderWidgets
maxHeight: parent.height - toolStrip.y + (_flightVideo.visible ? (_flightVideo.y - parent.height) : 0) maxHeight: parent.height - toolStrip.y + (_pipOverlay.visible ? (_pipOverlay.y - parent.height) : 0)
guidedActionsController: _guidedController guidedActionsController: _guidedController
guidedActionList: _guidedList guidedActionList: _guidedList
usePreFlightChecklist: preFlightChecklistPopup.useChecklist usePreFlightChecklist: preFlightChecklistPopup.useChecklist
@ -413,7 +256,7 @@ Item {
anchors.margins: _margins anchors.margins: _margins
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
z: _guidedZOrder z: QGroundControl.zOrderTopMost
guidedController: _guidedController guidedController: _guidedController
altitudeSlider: _guidedSlider altitudeSlider: _guidedSlider
} }
@ -423,7 +266,7 @@ Item {
anchors.margins: _margins anchors.margins: _margins
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
z: _guidedZOrder z: QGroundControl.zOrderTopMost
guidedController: _guidedController guidedController: _guidedController
} }
@ -435,7 +278,7 @@ Item {
anchors.topMargin: ScreenTools.toolbarHeight + _margins anchors.topMargin: ScreenTools.toolbarHeight + _margins
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
z: _guidedZOrder z: QGroundControl.zOrderTopMost
radius: ScreenTools.defaultFontPixelWidth / 2 radius: ScreenTools.defaultFontPixelWidth / 2
width: ScreenTools.defaultFontPixelWidth * 10 width: ScreenTools.defaultFontPixelWidth * 10
color: qgcPal.window color: qgcPal.window
@ -447,7 +290,7 @@ Item {
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.25 anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.25
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
show: mainIsMap show: _mainWindowIsMap
} }
FlyViewPreFlightChecklistPopup { FlyViewPreFlightChecklistPopup {

24
src/FlightDisplay/FlightDisplayViewMap.qml

@ -33,15 +33,13 @@ FlightMap {
zoomLevel: QGroundControl.flightMapZoom zoomLevel: QGroundControl.flightMapZoom
center: QGroundControl.flightMapPosition center: QGroundControl.flightMapPosition
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var guidedActionsController property var guidedActionsController
property var flightWidgets property var flightWidgets
property var rightPanelWidth property var rightPanelWidth
property var planMasterController property var planMasterController
property alias scaleState: mapScale.state
property rect centerViewport: Qt.rect(0, 0, width, height) property rect centerViewport: Qt.rect(0, 0, width, height)
property bool mainWindowIsMap: true
property var _planMasterController: planMasterController property var _planMasterController: planMasterController
property var _geoFenceController: planMasterController.geoFenceController property var _geoFenceController: planMasterController.geoFenceController
@ -53,7 +51,7 @@ FlightMap {
property bool _keepMapCenteredOnVehicle: _flyViewSettings.keepMapCenteredOnVehicle.rawValue property bool _keepMapCenteredOnVehicle: _flyViewSettings.keepMapCenteredOnVehicle.rawValue
property bool _disableVehicleTracking: false property bool _disableVehicleTracking: false
property bool _keepVehicleCentered: mainIsMap ? false : true property bool _keepVehicleCentered: mainWindowIsMap ? false : true
property bool _pipping: false property bool _pipping: false
function updateAirspace(reset) { function updateAirspace(reset) {
@ -81,7 +79,7 @@ FlightMap {
} }
function adjustMapSize() { function adjustMapSize() {
if(mainIsMap) if(mainWindowIsMap)
pipOut() pipOut()
else else
pipIn() pipIn()
@ -213,7 +211,7 @@ FlightMap {
MapFitFunctions { MapFitFunctions {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware! id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: mainWindow.flightDisplayMap map: flightMap
usePlannedHomePosition: false usePlannedHomePosition: false
planMasterController: _planMasterController planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width property real leftToolWidth: toolStrip.x + toolStrip.width
@ -225,7 +223,7 @@ FlightMap {
line.width: 3 line.width: 3
line.color: "red" line.color: "red"
z: QGroundControl.zOrderTrajectoryLines z: QGroundControl.zOrderTrajectoryLines
visible: mainIsMap visible: mainWindowIsMap
Connections { Connections {
target: QGroundControl.multiVehicleManager target: QGroundControl.multiVehicleManager
@ -247,7 +245,7 @@ FlightMap {
vehicle: object vehicle: object
coordinate: object.coordinate coordinate: object.coordinate
map: flightMap map: flightMap
size: mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight size: mainWindowIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
z: QGroundControl.zOrderVehicles z: QGroundControl.zOrderVehicles
} }
} }
@ -272,7 +270,7 @@ FlightMap {
PlanMapItems { PlanMapItems {
map: flightMap map: flightMap
largeMapView: mainIsMap largeMapView: mainWindowIsMap
planMasterController: _planMasterController planMasterController: _planMasterController
vehicle: _vehicle vehicle: _vehicle
@ -286,7 +284,7 @@ FlightMap {
} }
MapItemView { MapItemView {
model: mainIsMap ? _missionController.directionArrows : undefined model: mainWindowIsMap ? _missionController.directionArrows : undefined
delegate: MapLineArrow { delegate: MapLineArrow {
fromCoord: object ? object.coordinate1 : undefined fromCoord: object ? object.coordinate1 : undefined
@ -299,7 +297,7 @@ FlightMap {
// Allow custom builds to add map items // Allow custom builds to add map items
CustomMapItems { CustomMapItems {
map: flightMap map: flightMap
largeMapView: mainIsMap largeMapView: mainWindowIsMap
} }
GeoFenceMapVisuals { GeoFenceMapVisuals {
@ -556,7 +554,7 @@ FlightMap {
anchors.topMargin: _toolsMargin + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight anchors.topMargin: _toolsMargin + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
mapControl: flightMap mapControl: flightMap
buttonsOnLeft: false buttonsOnLeft: false
visible: !ScreenTools.isTinyScreen && QGroundControl.corePlugin.options.enableMapScale && mainIsMap visible: !ScreenTools.isTinyScreen && QGroundControl.corePlugin.options.enableMapScale && mainWindowIsMap
state: "bottomMode" state: "bottomMode"
states: [ states: [
State { State {

5
src/FlightDisplay/FlightDisplayViewVideo.qml

@ -23,6 +23,9 @@ import QGroundControl.Controllers 1.0
Item { Item {
id: root id: root
clip: true clip: true
property bool useSmallFont: true
property double _ar: QGroundControl.videoManager.aspectRatio property double _ar: QGroundControl.videoManager.aspectRatio
property bool _showGrid: QGroundControl.settingsManager.videoSettings.gridLines.rawValue > 0 property bool _showGrid: QGroundControl.settingsManager.videoSettings.gridLines.rawValue > 0
property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null
@ -44,7 +47,7 @@ Item {
text: QGroundControl.settingsManager.videoSettings.streamEnabled.rawValue ? qsTr("WAITING FOR VIDEO") : qsTr("VIDEO DISABLED") text: QGroundControl.settingsManager.videoSettings.streamEnabled.rawValue ? qsTr("WAITING FOR VIDEO") : qsTr("VIDEO DISABLED")
font.family: ScreenTools.demiboldFontFamily font.family: ScreenTools.demiboldFontFamily
color: "white" color: "white"
font.pointSize: mainIsMap ? ScreenTools.smallFontPointSize : ScreenTools.largeFontPointSize font.pointSize: useSmallFont ? ScreenTools.smallFontPointSize : ScreenTools.largeFontPointSize
anchors.centerIn: parent anchors.centerIn: parent
} }
MouseArea { MouseArea {

5
src/FlightDisplay/FlightDisplayViewWidgets.qml

@ -33,15 +33,12 @@ Item {
property var missionController property var missionController
property bool showValues: !QGroundControl.airspaceManager.airspaceVisible property bool showValues: !QGroundControl.airspaceManager.airspaceVisible
property bool _isSatellite: mainIsMap ? (mainWindow.flightDisplayMap ? mainWindow.flightDisplayMap.isSatelliteMap : true) : true property bool _lightWidgetBorders: true
property bool _lightWidgetBorders: _isSatellite
property bool _airspaceEnabled: QGroundControl.airmapSupported ? QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue : false property bool _airspaceEnabled: QGroundControl.airmapSupported ? QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue : false
readonly property real _margins: ScreenTools.defaultFontPixelHeight * 0.5 readonly property real _margins: ScreenTools.defaultFontPixelHeight * 0.5
readonly property bool _useAlternateInstrumentPanel: QGroundControl.settingsManager.flyViewSettings.alternateInstrumentPanel.value readonly property bool _useAlternateInstrumentPanel: QGroundControl.settingsManager.flyViewSettings.alternateInstrumentPanel.value
QGCMapPalette { id: mapPal; lightColors: useLightColors }
function getPreferredInstrumentWidth() { function getPreferredInstrumentWidth() {
// Don't allow instrument panel to chew more than 1/4 of full window // Don't allow instrument panel to chew more than 1/4 of full window
var defaultWidth = ScreenTools.defaultFontPixelWidth * 30 var defaultWidth = ScreenTools.defaultFontPixelWidth * 30

2
src/FlightMap/Widgets/QGCInstrumentWidget.qml

@ -43,7 +43,7 @@ ColumnLayout {
radius: _outerRadius radius: _outerRadius
color: qgcPal.window color: qgcPal.window
border.width: 1 border.width: 1
border.color: _isSatellite ? qgcPal.mapWidgetBorderLight : qgcPal.mapWidgetBorderDark border.color: qgcPal.mapWidgetBorderLight
DeadMouseArea { anchors.fill: parent } DeadMouseArea { anchors.fill: parent }

25
src/QmlControls/QGCControlDebug.qml

@ -0,0 +1,25 @@
/****************************************************************************
*
* (c) 2009-2020 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.12
Item {
property string name: "control"
Connections {
target: parent
onXChanged: console.log(name, "xChanged", parent.x)
onYChanged: console.log(name, "yChanged", parent.y)
onWidthChanged: console.log(name, "widthChanged", parent.width)
onHeightChanged: console.log(name, "heightChanged", parent.height)
onVisibleChanged: console.log(name, "visibleChanged", parent.visible)
onZChanged: console.log(name, "zChanged", parent.z)
onParentChanged: console.log(name, "parentChanged", parent.parent)
}
}

243
src/QmlControls/QGCPipOverlay.qml

@ -0,0 +1,243 @@
/****************************************************************************
*
* (c) 2009-2020 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.12
import QtQuick.Window 2.12
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
Item {
id: _root
width: _pipSize
height: _pipSize * (9/16)
z: pipZOrder + 1
visible: item2 && item2.pipState !== item2.pipState.window
property var item1: null // Required
property var item2: null // Optional, may come and go
property string item1IsFullSettingsKey // Settings key to save whether item1 was saved in full mode
property real fullZOrder: 0 // zOrder for items in full mode
property real pipZOrder: 1 // zOrder for items in pip mode
readonly property string _pipExpandedSettingsKey: "IsPIPVisible"
property var _fullItem
property var _pipOrWindowItem
property alias _windowContentItem: window.contentItem
property bool _isExpanded: true
property real _pipSize: parent.width * 0.2
property real _maxSize: 0.75 // Percentage of parent control size
property real _minSize: 0.10
property bool _componentComplete: false
Component.onCompleted: {
_initForItems()
_componentComplete = true
}
onItem2Changed: _initForItems()
function showWindow() {
window.width = _root.width
window.height = _root.height
window.show()
}
function _initForItems() {
var item1IsFull = QGroundControl.loadBoolGlobalSetting(item1IsFullSettingsKey, true)
if (item1 && item2) {
item1.pipState.state = item1IsFull ? item1.pipState.fullState : item1.pipState.pipState
item2.pipState.state = item1IsFull ? item2.pipState.pipState : item2.pipState.fullState
_fullItem = item1IsFull ? item1 : item2
_pipOrWindowItem = item1IsFull ? item2 : item1
} else {
item1.pipState.state = item1.pipState.fullState
_fullItem = item1
_pipOrWindowItem = null
}
_setPipIsExpanded(QGroundControl.loadBoolGlobalSetting(_pipExpandedSettingsKey, true))
}
function _swapPip() {
var item1IsFull = false
if (item1.pipState.state === item1.pipState.fullState) {
item1.pipState.state = item1.pipState.pipState
item2.pipState.state = item2.pipState.fullState
_fullItem = item2
_pipOrWindowItem = item1
item1IsFull = false
} else {
item1.pipState.state = item1.pipState.fullState
item2.pipState.state = item2.pipState.pipState
_fullItem = item1
_pipOrWindowItem = item2
item1IsFull = true
}
QGroundControl.saveBoolGlobalSetting(item1IsFullSettingsKey, item1IsFull)
}
function _setPipIsExpanded(isExpanded) {
QGroundControl.saveBoolGlobalSetting(_pipExpandedSettingsKey, isExpanded)
_isExpanded = isExpanded
if (_pipOrWindowItem) {
_pipOrWindowItem.visible = isExpanded
}
}
Window {
id: window
visible: false
onClosing: {
var item = contentItem.children[0]
item.pipState.windowAboutToClose()
item.pipState.state = item.pipState.windowClosingState
item.pipState.state = item.pipState.pipState
}
}
MouseArea {
id: pipMouseArea
anchors.fill: parent
enabled: _isExpanded
hoverEnabled: true
onClicked: _swapPip()
}
// MouseArea to drag in order to resize the PiP area
MouseArea {
id: pipResize
anchors.top: parent.top
anchors.right: parent.right
height: ScreenTools.minTouchPixels
width: height
property real initialX: 0
property real initialWidth: 0
// When we push the mouse button down, we un-anchor the mouse area to prevent a resizing loop
onPressed: {
pipResize.anchors.top = undefined // Top doesn't seem to 'detach'
pipResize.anchors.right = undefined // This one works right, which is what we really need
pipResize.initialX = mouse.x
pipResize.initialWidth = _root.width
}
// When we let go of the mouse button, we re-anchor the mouse area in the correct position
onReleased: {
pipResize.anchors.top = _root.top
pipResize.anchors.right = _root.right
}
// Drag
onPositionChanged: {
if (pipResize.pressed) {
var parentWidth = _root.parent.width
var newWidth = pipResize.initialWidth + mouse.x - pipResize.initialX
if (newWidth < parentWidth * _maxSize && newWidth > parentWidth * _minSize) {
_pipSize = newWidth
}
}
}
}
// Resize icon
Image {
source: "/qmlimages/pipResize.svg"
fillMode: Image.PreserveAspectFit
mipmap: true
anchors.right: parent.right
anchors.top: parent.top
visible: _isExpanded && (ScreenTools.isMobile || pipMouseArea.containsMouse)
height: ScreenTools.defaultFontPixelHeight * 2.5
width: ScreenTools.defaultFontPixelHeight * 2.5
sourceSize.height: height
}
// Check min/max constraints on pip size when when parent is resized
Connections {
target: _root.parent
onWidthChanged: {
if (!_componentComplete) {
// Wait until first time setup is done
return
}
var parentWidth = _root.parent.width
if (_root.width > parentWidth * _maxSize) {
_pipSize = parentWidth * _maxSize
} else if (_root.width < parentWidth * _minSize) {
_pipSize = parentWidth * _minSize
}
}
}
// Pip to Window
Image {
id: popupPIP
source: "/qmlimages/PiP.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.left: parent.left
anchors.top: parent.top
visible: _isExpanded && !ScreenTools.isMobile && pipMouseArea.containsMouse
height: ScreenTools.defaultFontPixelHeight * 2.5
width: ScreenTools.defaultFontPixelHeight * 2.5
sourceSize.height: height
MouseArea {
anchors.fill: parent
onClicked: _pipOrWindowItem.pipState.state = _pipOrWindowItem.pipState.windowState
}
}
Image {
id: hidePIP
source: "/qmlimages/pipHide.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.left: parent.left
anchors.bottom: parent.bottom
visible: _isExpanded && (ScreenTools.isMobile || pipMouseArea.containsMouse)
height: ScreenTools.defaultFontPixelHeight * 2.5
width: ScreenTools.defaultFontPixelHeight * 2.5
sourceSize.height: height
MouseArea {
anchors.fill: parent
onClicked: _root._setPipIsExpanded(false)
}
}
Rectangle {
id: showPip
anchors.left : parent.left
anchors.bottom: parent.bottom
height: ScreenTools.defaultFontPixelHeight * 2
width: ScreenTools.defaultFontPixelHeight * 2
radius: ScreenTools.defaultFontPixelHeight / 3
visible: !_isExpanded
color: _fullItem.pipState.isDark ? Qt.rgba(0,0,0,0.75) : Qt.rgba(0,0,0,0.5)
Image {
width: parent.width * 0.75
height: parent.height * 0.75
sourceSize.height: height
source: "/res/buttonRight.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
MouseArea {
anchors.fill: parent
onClicked: _root._setPipIsExpanded(true)
}
}
}

96
src/QmlControls/QGCPipState.qml

@ -0,0 +1,96 @@
/****************************************************************************
*
* (c) 2009-2020 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.12
// Used to manage state for itesm using with QGCPipOveral
Item {
id: _root
state: initState
readonly property string initState: "init"
readonly property string pipState: "pip"
readonly property string fullState: "full"
readonly property string windowState: "window"
readonly property string windowClosingState: "windowClosing"
property var pipOverlay // QGCPipOverlay control
property bool isDark: true // true: Use dark overlay visuals
signal windowAboutToOpen // Catch this signal to do something special prior to the item transition to windowed mode
signal windowAboutToClose // Catch this signal to do special processing prior to the item transition back to pip mode
property var _clientControl: _root.parent
states: [
State {
name: pipState
AnchorChanges {
target: _clientControl
anchors.top: pipOverlay.top
anchors.bottom: pipOverlay.bottom
anchors.left: pipOverlay.left
anchors.right: pipOverlay.right
}
PropertyChanges {
target: _clientControl
z: pipOverlay.pipZOrder
}
},
State {
name: fullState
AnchorChanges {
target: _clientControl
anchors.top: pipOverlay.parent.top
anchors.bottom: pipOverlay.parent.bottom
anchors.left: pipOverlay.parent.left
anchors.right: pipOverlay.parent.right
}
PropertyChanges {
target: _clientControl
z: pipOverlay.fullZOrder
}
},
State {
name: windowState
AnchorChanges {
target: _root.parent
anchors.top: pipOverlay._windowContentItem.top
anchors.bottom: pipOverlay._windowContentItem.bottom
anchors.left: pipOverlay._windowContentItem.left
anchors.right: pipOverlay._windowContentItem.right
}
ParentChange {
target: _root.parent
parent: pipOverlay._windowContentItem
}
StateChangeScript {
script: {
_root.windowAboutToOpen()
pipOverlay.showWindow()
}
}
},
State {
name: windowClosingState
ParentChange {
target: _root.parent
parent: pipOverlay.parent
}
}
]
}

191
src/QmlControls/QGCPipable.qml

@ -1,191 +0,0 @@
/****************************************************************************
*
* (c) 2009-2020 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 QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
Item {
id: pip
property bool isHidden: false
property bool isDark: false
// As a percentage of the window width
property real maxSize: 0.75
property real minSize: 0.10
property bool inPopup: false
property bool enablePopup: true
signal activated()
signal hideIt(bool state)
signal newWidth(real newWidth)
signal popup()
MouseArea {
id: pipMouseArea
anchors.fill: parent
enabled: !isHidden
hoverEnabled: true
onClicked: {
pip.activated()
}
}
// MouseArea to drag in order to resize the PiP area
MouseArea {
id: pipResize
anchors.top: parent.top
anchors.right: parent.right
height: ScreenTools.minTouchPixels
width: height
property real initialX: 0
property real initialWidth: 0
onClicked: {
// TODO propagate
}
// When we push the mouse button down, we un-anchor the mouse area to prevent a resizing loop
onPressed: {
pipResize.anchors.top = undefined // Top doesn't seem to 'detach'
pipResize.anchors.right = undefined // This one works right, which is what we really need
pipResize.initialX = mouse.x
pipResize.initialWidth = pip.width
}
// When we let go of the mouse button, we re-anchor the mouse area in the correct position
onReleased: {
pipResize.anchors.top = pip.top
pipResize.anchors.right = pip.right
}
// Drag
onPositionChanged: {
if (pipResize.pressed) {
var parentW = pip.parent.width // flightView
var newW = pipResize.initialWidth + mouse.x - pipResize.initialX
if (newW < parentW * maxSize && newW > parentW * minSize) {
newWidth(newW)
}
}
}
}
// Resize icon
Image {
source: "/qmlimages/pipResize.svg"
fillMode: Image.PreserveAspectFit
mipmap: true
anchors.right: parent.right
anchors.top: parent.top
visible: !isHidden && (ScreenTools.isMobile || pipMouseArea.containsMouse) && !inPopup
height: ScreenTools.defaultFontPixelHeight * 2.5
width: ScreenTools.defaultFontPixelHeight * 2.5
sourceSize.height: height
}
// Resize pip window if necessary when main window is resized
property int pipLock: 2
Connections {
target: pip.parent
onWidthChanged: {
// hackity hack...
// don't fire this while app is loading/initializing (it happens twice)
if (pipLock) {
pipLock--
return
}
var parentW = pip.parent.width
if (pip.width > parentW * maxSize) {
newWidth(parentW * maxSize)
} else if (pip.width < parentW * minSize) {
newWidth(parentW * minSize)
}
}
}
//-- PIP Popup Indicator
Image {
id: popupPIP
source: "/qmlimages/PiP.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.left: parent.left
anchors.top: parent.top
visible: !isHidden && !inPopup && !ScreenTools.isMobile && enablePopup && pipMouseArea.containsMouse
height: ScreenTools.defaultFontPixelHeight * 2.5
width: ScreenTools.defaultFontPixelHeight * 2.5
sourceSize.height: height
MouseArea {
anchors.fill: parent
onClicked: {
inPopup = true
pip.popup()
}
}
}
//-- PIP Corner Indicator
Image {
id: closePIP
source: "/qmlimages/pipHide.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.left: parent.left
anchors.bottom: parent.bottom
visible: !isHidden && (ScreenTools.isMobile || pipMouseArea.containsMouse)
height: ScreenTools.defaultFontPixelHeight * 2.5
width: ScreenTools.defaultFontPixelHeight * 2.5
sourceSize.height: height
MouseArea {
anchors.fill: parent
onClicked: {
pip.hideIt(true)
}
}
}
//-- Show PIP
Rectangle {
id: openPIP
anchors.left : parent.left
anchors.bottom: parent.bottom
height: ScreenTools.defaultFontPixelHeight * 2
width: ScreenTools.defaultFontPixelHeight * 2
radius: ScreenTools.defaultFontPixelHeight / 3
visible: isHidden
color: isDark ? Qt.rgba(0,0,0,0.75) : Qt.rgba(0,0,0,0.5)
Image {
width: parent.width * 0.75
height: parent.height * 0.75
sourceSize.height: height
source: "/res/buttonRight.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pip.hideIt(false)
}
}
}
}

4
src/QmlControls/QGroundControl/Controls/qmldir

@ -50,6 +50,7 @@ QGCButton 1.0 QGCButton.qml
QGCCheckBox 1.0 QGCCheckBox.qml QGCCheckBox 1.0 QGCCheckBox.qml
QGCColoredImage 1.0 QGCColoredImage.qml QGCColoredImage 1.0 QGCColoredImage.qml
QGCComboBox 1.0 QGCComboBox.qml QGCComboBox 1.0 QGCComboBox.qml
QGCControlDebug 1.0 QGCControlDebug.qml
QGCDynamicObjectManager 1.0 QGCDynamicObjectManager.qml QGCDynamicObjectManager 1.0 QGCDynamicObjectManager.qml
QGCFileDialog 1.0 QGCFileDialog.qml QGCFileDialog 1.0 QGCFileDialog.qml
QGCFlickable 1.0 QGCFlickable.qml QGCFlickable 1.0 QGCFlickable.qml
@ -66,7 +67,8 @@ QGCMenuSeparator 1.0 QGCMenuSeparator.qml
QGCMouseArea 1.0 QGCMouseArea.qml QGCMouseArea 1.0 QGCMouseArea.qml
QGCMovableItem 1.0 QGCMovableItem.qml QGCMovableItem 1.0 QGCMovableItem.qml
QGCOptionsComboBox 1.0 QGCOptionsComboBox.qml QGCOptionsComboBox 1.0 QGCOptionsComboBox.qml
QGCPipable 1.0 QGCPipable.qml QGCPipOverlay 1.0 QGCPipOverlay.qml
QGCPipState 1.0 QGCPipState.qml
QGCPopupDialog 1.0 QGCPopupDialog.qml QGCPopupDialog 1.0 QGCPopupDialog.qml
QGCPopupDialogContainer 1.0 QGCPopupDialogContainer.qml QGCPopupDialogContainer 1.0 QGCPopupDialogContainer.qml
QGCRadioButton 1.0 QGCRadioButton.qml QGCRadioButton 1.0 QGCRadioButton.qml

1
src/ui/MainRootWindow.qml

@ -68,7 +68,6 @@ ApplicationWindow {
property var currentPlanMissionItem: planMasterControllerPlan ? planMasterControllerPlan.missionController.currentPlanViewItem : null property var currentPlanMissionItem: planMasterControllerPlan ? planMasterControllerPlan.missionController.currentPlanViewItem : null
property var planMasterControllerPlan: null property var planMasterControllerPlan: null
property var planMasterControllerView: null property var planMasterControllerView: null
property var flightDisplayMap: null
readonly property string navButtonWidth: ScreenTools.defaultFontPixelWidth * 24 readonly property string navButtonWidth: ScreenTools.defaultFontPixelWidth * 24
readonly property real defaultTextHeight: ScreenTools.defaultFontPixelHeight readonly property real defaultTextHeight: ScreenTools.defaultFontPixelHeight

Loading…
Cancel
Save