QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
ParameterEditor.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Dialogs
4import QtQuick.Layouts
5
6import QGroundControl
7import QGroundControl.Controls
8import QGroundControl.FactControls
9
10Item {
11 id: _root
12
13 property Fact _editorDialogFact: Fact { }
14 property int _rowHeight: ScreenTools.defaultFontPixelHeight * 2
15 property int _rowWidth: 10 // Dynamic adjusted at runtime
16 property bool _searchFilter: searchText.text.trim() != "" || controller.showModifiedOnly ///< true: showing results of search
17 property var _searchResults ///< List of parameter names from search results
18 property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
19 property bool _showRCToParam: _activeVehicle.px4Firmware
20 property var _appSettings: QGroundControl.settingsManager.appSettings
21 property var _controller: controller
22
23 ParameterEditorController {
24 id: controller
25 }
26
27 Timer {
28 id: clearTimer
29 interval: 100;
30 running: false;
31 repeat: false
32 onTriggered: {
33 searchText.text = ""
34 controller.searchText = ""
35 }
36 }
37
38 QGCMenu {
39 id: toolsMenu
40 QGCMenuItem {
41 text: qsTr("Refresh")
42 onTriggered: controller.refresh()
43 }
44 QGCMenuItem {
45 text: qsTr("Reset all to firmware's defaults")
46 onTriggered: QGroundControl.showMessageDialog(_root, qsTr("Reset All"),
47 qsTr("Select Reset to reset all parameters to their defaults.\n\nNote that this will also completely reset everything, including UAVCAN nodes, all vehicle settings, setup and calibrations."),
48 Dialog.Cancel | Dialog.Reset,
49 function() { controller.resetAllToDefaults() })
50 }
51 QGCMenuItem {
52 text: qsTr("Reset to vehicle's configuration defaults")
53 visible: !_activeVehicle.apmFirmware
54 onTriggered: QGroundControl.showMessageDialog(_root, qsTr("Reset All"),
55 qsTr("Select Reset to reset all parameters to the vehicle's configuration defaults."),
56 Dialog.Cancel | Dialog.Reset,
57 function() { controller.resetAllToVehicleConfiguration() })
58 }
59 QGCMenuSeparator { }
60 QGCMenuItem {
61 text: qsTr("Load from file for review...")
62 onTriggered: {
63 fileDialog.title = qsTr("Load Parameters")
64 fileDialog.openForLoad()
65 }
66 }
67 QGCMenuItem {
68 text: qsTr("Save to file...")
69 onTriggered: {
70 fileDialog.title = qsTr("Save Parameters")
71 fileDialog.openForSave()
72 }
73 }
74 QGCMenuSeparator { visible: _showRCToParam }
75 QGCMenuItem {
76 text: qsTr("Clear all RC to Param")
77 onTriggered: _activeVehicle.clearAllParamMapRC()
78 visible: _showRCToParam
79 }
80 QGCMenuSeparator { }
81 QGCMenuItem {
82 text: qsTr("Reboot Vehicle")
83 onTriggered: QGroundControl.showMessageDialog(_root, qsTr("Reboot Vehicle"),
84 qsTr("Select Ok to reboot vehicle."),
85 Dialog.Cancel | Dialog.Ok,
86 function() { _activeVehicle.rebootVehicle() })
87 }
88 }
89
90
91 QGCFileDialog {
92 id: fileDialog
93 folder: _appSettings.parameterSavePath
94 nameFilters: [ qsTr("Parameter Files (*.%1)").arg(_appSettings.parameterFileExtension) , qsTr("All Files (*)") ]
95
96 onAcceptedForSave: (file) => {
97 controller.saveToFile(file)
98 close()
99 }
100
101 onAcceptedForLoad: (file) => {
102 close()
103 if (controller.buildDiffFromFile(file)) {
104 parameterDiffDialogFactory.open()
105 }
106 }
107 }
108
109 QGCPopupDialogFactory {
110 id: editorDialogFactory
111
112 dialogComponent: editorDialogComponent
113 }
114
115 Component {
116 id: editorDialogComponent
117
118 ParameterEditorDialog {
119 fact: _editorDialogFact
120 showRCToParam: _showRCToParam
121 }
122 }
123
124 QGCPopupDialogFactory {
125 id: parameterDiffDialogFactory
126
127 dialogComponent: parameterDiffDialog
128 }
129
130 Component {
131 id: parameterDiffDialog
132
133 ParameterDiffDialog {
134 paramController: _controller
135 }
136 }
137
138 RowLayout {
139 id: header
140 anchors.left: parent.left
141 anchors.right: parent.right
142
143 RowLayout {
144 Layout.alignment: Qt.AlignLeft
145 spacing: ScreenTools.defaultFontPixelWidth
146
147 QGCTextField {
148 id: searchText
149 placeholderText: qsTr("Search")
150 onDisplayTextChanged: controller.searchText = displayText
151 }
152
153 QGCButton {
154 text: qsTr("Clear")
155 onClicked: {
156 if(ScreenTools.isMobile) {
157 Qt.inputMethod.hide();
158 }
159 clearTimer.start()
160 }
161 }
162
163 QGCCheckBox {
164 text: qsTr("Show modified only")
165 checked: controller.showModifiedOnly
166 onClicked: controller.showModifiedOnly = checked
167 visible: QGroundControl.multiVehicleManager.activeVehicle.px4Firmware
168 }
169 }
170
171 QGCButton {
172 Layout.alignment: Qt.AlignRight
173 text: qsTr("Tools")
174 onClicked: toolsMenu.popup()
175 }
176 }
177
178 /// Group buttons
179 QGCFlickable {
180 id : groupScroll
181 width: ScreenTools.defaultFontPixelWidth * 25
182 anchors.top: header.bottom
183 anchors.bottom: parent.bottom
184 clip: true
185 pixelAligned: true
186 contentHeight: groupedViewCategoryColumn.height
187 flickableDirection: Flickable.VerticalFlick
188 visible: !_searchFilter
189
190 ColumnLayout {
191 id: groupedViewCategoryColumn
192 anchors.left: parent.left
193 anchors.right: parent.right
194 spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
195
196 Repeater {
197 model: controller.categories
198
199 Column {
200 Layout.fillWidth: true
201 spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
202
203
204 SectionHeader {
205 id: categoryHeader
206 anchors.left: parent.left
207 anchors.right: parent.right
208 text: object.name
209 checked: object == controller.currentCategory
210
211 onCheckedChanged: {
212 if (checked) {
213 controller.currentCategory = object
214 }
215 }
216 }
217
218 Repeater {
219 model: categoryHeader.checked ? object.groups : 0
220
221 QGCButton {
222 width: ScreenTools.defaultFontPixelWidth * 25
223 text: object.name
224 height: _rowHeight
225 checked: object == controller.currentGroup
226 autoExclusive: true
227
228 onClicked: {
229 if (!checked) _rowWidth = 10
230 checked = true
231 controller.currentGroup = object
232 }
233 }
234 }
235 }
236 }
237 }
238 }
239
240 TableView {
241 id: tableView
242 anchors.leftMargin: ScreenTools.defaultFontPixelWidth
243 anchors.top: header.bottom
244 anchors.bottom: parent.bottom
245 anchors.left: _searchFilter ? parent.left : groupScroll.right
246 anchors.right: parent.right
247 columnSpacing: ScreenTools.defaultFontPixelWidth
248 rowSpacing: ScreenTools.defaultFontPixelHeight / 4
249 model: controller.parameters
250 contentWidth: width
251 clip: true
252
253 // Qt is supposed to adjust column widths automatically when larger widths come into view.
254 // But it doesn't work. So we have to do it force a layout manually when we scroll.
255 Timer {
256 id: forceLayoutTimer
257 interval: 500
258 repeat: false
259 onTriggered: tableView.forceLayout()
260 }
261
262 onTopRowChanged: forceLayoutTimer.start()
263 onModelChanged: {
264 positionViewAtRow(0, TableView.AlignLeft | TableView.AlignTop)
265 forceLayoutTimer.start()
266 }
267
268 delegate: Item {
269 implicitWidth: label.contentWidth
270 implicitHeight: label.contentHeight
271 clip: true
272
273 QGCLabel {
274 id: label
275 width: column == 1 ? ScreenTools.defaultFontPixelWidth * 15 : contentWidth
276 text: column == 1 ? col1String() : display
277 color: column == 1 ? col1Color() : qgcPal.text
278 maximumLineCount: 1
279 elide: column == 1 ? Text.ElideRight : Text.ElideNone
280
281 Component.onCompleted: {
282 return
283 if (tableView.columnWidth(column) < width) {
284 console.log("setColumnWidth", column, width)
285 tableView.setColumnWidth(column, width)
286 }
287 }
288
289 function col1String() {
290 if (fact.enumStrings.length === 0) {
291 return fact.valueString + " " + fact.units
292 }
293 if (fact.bitmaskStrings.length != 0) {
294 return fact.selectedBitmaskStrings.join(',')
295 }
296 return fact.enumStringValue
297 }
298
299 function col1Color() {
300 if (fact.defaultValueAvailable) {
301 return fact.valueEqualsDefault ? qgcPal.text : qgcPal.warningText
302 } else {
303 return qgcPal.text
304 }
305 }
306 }
307
308 QGCMouseArea {
309 anchors.fill: parent
310 onClicked: mouse => {
311 _editorDialogFact = fact
312 editorDialogFactory.open()
313 }
314 }
315 }
316 }
317}