QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
PipView.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Window
3
4import QGroundControl
5import QGroundControl.Controls
6
7Item {
8 id: _root
9 width: _pipSize
10 height: _pipSize * (9/16)
11 visible: item2 && item2.pipState !== item2.pipState.window && show
12
13 property var item1: null // Required
14 property var item2: null // Optional, may come and go
15 property string item1IsFullSettingsKey // Settings key to save whether item1 was saved in full mode
16 property bool show: true
17
18 // Area covering the parent, in PipView coordinates: just the restore button while collapsed
19 readonly property rect occupiedRect: _isExpanded ? Qt.rect(0, 0, width, height) : Qt.rect(showPip.x, showPip.y, showPip.width, showPip.height)
20
21 readonly property string _pipExpandedSettingsKey: "IsPIPVisible"
22
23 property var _fullItem
24 property var _pipOrWindowItem
25 property alias _windowContentItem: window.contentItem
26 property alias _pipContentItem: pipContent
27 property bool _isExpanded: true
28 property real _pipSize: parent.width * 0.2
29 property real _maxSize: 0.75 // Percentage of parent control size
30 property real _minSize: 0.10
31 property bool _componentComplete: false
32
33 Component.onCompleted: {
34 _initForItems()
35 _componentComplete = true
36 }
37
38 // item1 can swap at runtime (fly view map engine Loader), not just item2
39 onItem1Changed: _initForItems()
40 onItem2Changed: _initForItems()
41
42 function showWindow() {
43 window.width = _root.width
44 window.height = _root.height
45 window.show()
46 }
47
48 function _initForItems() {
49 if (!item1) {
50 // Engine swap in flight: wait for the new item1
51 _fullItem = null
52 _pipOrWindowItem = null
53 return
54 }
55 var item1IsFull = QGroundControl.loadBoolGlobalSetting(item1IsFullSettingsKey, true)
56 if (item1 && item2) {
57 item1.pipState.state = item1IsFull ? item1.pipState.fullState : item1.pipState.pipState
58 item2.pipState.state = item1IsFull ? item2.pipState.pipState : item2.pipState.fullState
59 _fullItem = item1IsFull ? item1 : item2
60 _pipOrWindowItem = item1IsFull ? item2 : item1
61 } else {
62 item1.pipState.state = item1.pipState.fullState
63 _fullItem = item1
64 _pipOrWindowItem = null
65 }
66 _setPipIsExpanded(QGroundControl.loadBoolGlobalSetting(_pipExpandedSettingsKey, true))
67 }
68
69 function _swapPip() {
70 if (!item1 || !item2) {
71 // Engine swap in flight (see _initForItems)
72 return
73 }
74 var item1IsFull = false
75 if (item1.pipState.state === item1.pipState.fullState) {
76 item1.pipState.state = item1.pipState.pipState
77 item2.pipState.state = item2.pipState.fullState
78 _fullItem = item2
79 _pipOrWindowItem = item1
80 item1IsFull = false
81 } else {
82 item1.pipState.state = item1.pipState.fullState
83 item2.pipState.state = item2.pipState.pipState
84 _fullItem = item1
85 _pipOrWindowItem = item2
86 item1IsFull = true
87 }
88 QGroundControl.saveBoolGlobalSetting(item1IsFullSettingsKey, item1IsFull)
89 }
90
91 function _setPipIsExpanded(isExpanded) {
92 QGroundControl.saveBoolGlobalSetting(_pipExpandedSettingsKey, isExpanded)
93 _isExpanded = isExpanded
94 }
95
96 Window {
97 id: window
98 visible: false
99 onClosing: {
100 var item = contentItem.children[0]
101 if (item) {
102 item.pipState.windowAboutToClose()
103 item.pipState.state = item.pipState.pipState
104 }
105 }
106 }
107
108 Item {
109 id: pipContent
110 anchors.fill: parent
111 visible: _isExpanded
112 clip: true
113 }
114
115 MouseArea {
116 id: pipMouseArea
117 anchors.fill: parent
118 enabled: _isExpanded
119 preventStealing: true
120 hoverEnabled: true
121 onClicked: _swapPip()
122 }
123
124 // MouseArea to drag in order to resize the PiP area
125 MouseArea {
126 id: pipResize
127 anchors.fill: pipResizeIcon
128 preventStealing: true
129 cursorShape: Qt.PointingHandCursor
130
131 property real initialX: 0
132 property real initialWidth: 0
133
134 onPressed: (mouse) => {
135 // Remove the anchor so the our mouse coordinates stay in the same original place for drag tracking
136 pipResize.anchors.fill = undefined
137 pipResize.initialX = mouse.x
138 pipResize.initialWidth = _root.width
139 }
140
141 onReleased: pipResize.anchors.fill = pipResizeIcon
142
143 // Drag
144 onPositionChanged: (mouse) => {
145 if (pipResize.pressed) {
146 var parentWidth = _root.parent.width
147 var newWidth = pipResize.initialWidth + mouse.x - pipResize.initialX
148 if (newWidth < parentWidth * _maxSize && newWidth > parentWidth * _minSize) {
149 _pipSize = newWidth
150 }
151 }
152 }
153 }
154
155 // Resize icon
156 Image {
157 id: pipResizeIcon
158 source: "/qmlimages/pipResize.svg"
159 fillMode: Image.PreserveAspectFit
160 mipmap: true
161 anchors.right: parent.right
162 anchors.top: parent.top
163 visible: _isExpanded && (ScreenTools.isMobile || pipMouseArea.containsMouse)
164 height: ScreenTools.defaultFontPixelHeight * 2.5
165 width: ScreenTools.defaultFontPixelHeight * 2.5
166 sourceSize.height: height
167 }
168
169 // Check min/max constraints on pip size when when parent is resized
170 Connections {
171 target: _root.parent
172
173 function onWidthChanged() {
174 if (!_componentComplete) {
175 // Wait until first time setup is done
176 return
177 }
178 var parentWidth = _root.parent.width
179 if (_root.width > parentWidth * _maxSize) {
180 _pipSize = parentWidth * _maxSize
181 } else if (_root.width < parentWidth * _minSize) {
182 _pipSize = parentWidth * _minSize
183 }
184 }
185 }
186
187 // Pip to Window
188 Image {
189 id: popupPIP
190 source: "/qmlimages/PiP.svg"
191 mipmap: true
192 fillMode: Image.PreserveAspectFit
193 anchors.left: parent.left
194 anchors.top: parent.top
195 visible: _isExpanded && !ScreenTools.isMobile && pipMouseArea.containsMouse
196 height: ScreenTools.defaultFontPixelHeight * 2.5
197 width: ScreenTools.defaultFontPixelHeight * 2.5
198 sourceSize.height: height
199
200 MouseArea {
201 anchors.fill: parent
202 onClicked: {
203 if (_pipOrWindowItem) {
204 _pipOrWindowItem.pipState.state = _pipOrWindowItem.pipState.windowState
205 }
206 }
207 }
208 }
209
210 Image {
211 id: hidePIP
212 source: "/qmlimages/pipHide.svg"
213 mipmap: true
214 fillMode: Image.PreserveAspectFit
215 anchors.left: parent.left
216 anchors.bottom: parent.bottom
217 visible: _isExpanded && (ScreenTools.isMobile || pipMouseArea.containsMouse)
218 height: ScreenTools.defaultFontPixelHeight * 2.5
219 width: ScreenTools.defaultFontPixelHeight * 2.5
220 sourceSize.height: height
221 MouseArea {
222 anchors.fill: parent
223 onClicked: _root._setPipIsExpanded(false)
224 }
225 }
226
227 Rectangle {
228 id: showPip
229 anchors.left : parent.left
230 anchors.bottom: parent.bottom
231 height: ScreenTools.defaultFontPixelHeight * 2
232 width: ScreenTools.defaultFontPixelHeight * 2
233 radius: ScreenTools.defaultFontPixelHeight / 3
234 visible: !_isExpanded
235 color: _fullItem.pipState.isDark ? Qt.rgba(0,0,0,0.75) : Qt.rgba(0,0,0,0.5)
236 Image {
237 width: parent.width * 0.75
238 height: parent.height * 0.75
239 sourceSize.height: height
240 source: "/res/buttonRight.svg"
241 mipmap: true
242 fillMode: Image.PreserveAspectFit
243 anchors.verticalCenter: parent.verticalCenter
244 anchors.horizontalCenter: parent.horizontalCenter
245 }
246 MouseArea {
247 anchors.fill: parent
248 onClicked: _root._setPipIsExpanded(true)
249 }
250 }
251}