6import QGroundControl.Controls
8/// Parameters tab for the Log Viewer.
9/// Owns all filter state; call applyFilter() after a log loads or clears.
13 required property var logParser
15 spacing: ScreenTools.defaultFontPixelHeight * 0.5
17 // -------------------------------------------------------------------------
19 // -------------------------------------------------------------------------
20 property string _parameterSearchText: ""
21 property bool _showOnlyChangedParameters: true
22 property var _filteredParameters: []
24 QGCPalette { id: qgcPal }
26 // -------------------------------------------------------------------------
28 // -------------------------------------------------------------------------
30 /// Recompute the filtered parameter list. Call after log load or clear.
31 function applyFilter() {
32 const query = String(_parameterSearchText).trim().toLowerCase()
33 const onlyChanged = _showOnlyChangedParameters
36 for (let i = 0; i < logParser.parameters.length; i++) {
37 const item = logParser.parameters[i]
38 // "Show only changed" filter: skip parameters that equal their system default
39 if (onlyChanged && item.hasDefault && item.isDefault) {
42 if (query.length > 0) {
43 const name = String(item.name)
44 const desc = item.shortDescription ? String(item.shortDescription) : ""
45 const value = String(item.value)
46 if ((name + " " + value + " " + desc).toLowerCase().indexOf(query) === -1) {
52 _filteredParameters = output
55 // -------------------------------------------------------------------------
57 // -------------------------------------------------------------------------
60 Layout.fillWidth: true
61 spacing: ScreenTools.defaultFontPixelWidth
64 id: _parameterSearchField
65 Layout.fillWidth: true
66 textColor: qgcPal.textFieldText
67 placeholderTextColor: Qt.rgba(qgcPal.textFieldText.r, qgcPal.textFieldText.g, qgcPal.textFieldText.b, 0.7)
68 placeholderText: qsTr("Search parameters")
71 control._parameterSearchText = text
72 if (text.trim().length === 0) {
73 _parameterSearchTimer.stop()
76 _parameterSearchTimer.restart()
81 control._parameterSearchText = text
82 _parameterSearchTimer.stop()
88 text: qsTr("Changed only")
89 checked: _showOnlyChangedParameters
91 control._showOnlyChangedParameters = checked
98 Layout.fillWidth: true
99 Layout.fillHeight: true
104 model: _filteredParameters
105 spacing: ScreenTools.defaultFontPixelHeight * 0.1
107 ScrollBar.vertical: ScrollBar { }
109 delegate: Rectangle {
110 width: ListView.view.width
111 height: _paramRow.implicitHeight + ScreenTools.defaultFontPixelHeight * 0.4
112 color: index % 2 === 0 ? qgcPal.windowShade : qgcPal.windowShadeDark
115 // Format value: use metadata decimalPlaces when available,
116 // fall back to isFloat heuristic. Show enum label when applicable.
117 readonly property string _formattedValue: {
118 const v = modelData.value
119 if (v === undefined || v === null) return qsTr("N/A")
120 const numV = Number(v)
121 // Enum: find matching label
122 const eStrs = modelData.enumStrings
123 const eVals = modelData.enumValues
124 if (eStrs && eVals && eStrs.length > 0 && eVals.length === eStrs.length) {
125 for (let ei = 0; ei < eVals.length; ei++) {
126 if (Number(eVals[ei]) === numV) {
127 return eStrs[ei] + " (" + Math.round(numV) + ")"
131 // Numeric: metadata decimalPlaces wins
132 const dp = (modelData.decimalPlaces !== undefined) ? modelData.decimalPlaces : -1
135 formatted = numV.toFixed(dp)
136 } else if (modelData.isFloat) {
137 formatted = numV.toFixed(6)
139 formatted = String(Math.round(numV))
141 const units = (modelData.units && modelData.units.length > 0) ? (" " + modelData.units) : ""
142 return formatted + units
145 readonly property string _defaultText: {
146 if (!modelData.hasDefault) return ""
147 const d = modelData.defaultValue
148 if (d === undefined || d === null) return ""
149 const numD = Number(d)
150 const dp = (modelData.decimalPlaces !== undefined) ? modelData.decimalPlaces : -1
153 formatted = numD.toFixed(dp)
154 } else if (modelData.isFloat) {
155 formatted = numD.toFixed(6)
157 formatted = String(Math.round(numD))
159 return qsTr(" (default: %1)").arg(formatted)
164 anchors.verticalCenter: parent.verticalCenter
165 anchors.left: parent.left
166 anchors.right: parent.right
167 anchors.margins: ScreenTools.defaultFontPixelWidth * 0.5
168 spacing: ScreenTools.defaultFontPixelWidth * 0.5
170 // Changed-from-default indicator dot
172 visible: modelData.hasDefault && !modelData.isDefault
173 width: ScreenTools.defaultFontPixelHeight * 0.5
176 color: qgcPal.colorOrange
177 Layout.alignment: Qt.AlignVCenter
180 // Spacer to keep alignment when dot is hidden
182 visible: !(modelData.hasDefault && !modelData.isDefault)
183 width: ScreenTools.defaultFontPixelHeight * 0.5
189 font.bold: modelData.hasDefault && !modelData.isDefault
190 Layout.preferredWidth: ScreenTools.defaultFontPixelWidth * 22
191 elide: Text.ElideRight
195 text: _formattedValue
196 Layout.preferredWidth: ScreenTools.defaultFontPixelWidth * 14
197 horizontalAlignment: Text.AlignRight
202 color: Qt.rgba(qgcPal.text.r, qgcPal.text.g, qgcPal.text.b, 0.6)
203 Layout.preferredWidth: ScreenTools.defaultFontPixelWidth * 16
204 elide: Text.ElideRight
208 text: modelData.shortDescription ? String(modelData.shortDescription) : ""
209 color: Qt.rgba(qgcPal.text.r, qgcPal.text.g, qgcPal.text.b, 0.6)
210 Layout.fillWidth: true
211 elide: Text.ElideRight
219 id: _parameterSearchTimer
222 onTriggered: control.applyFilter()