8#include <QtCore/QJsonArray>
9#include <QtCore/QJsonDocument>
10#include <QtCore/QJsonObject>
11#include <QtQml/QQmlContext>
12#include <QtQuick/QQuickItem>
19 , _autopilot(autopilot)
20 , _KnownVehicleComponent(KnownVehicleComponent)
24 if (!vehicle || !autopilot) {
25 qCWarning(VehicleComponentLog) <<
"Internal error";
36 _ensureSectionsCached();
38 if (_repeatFilters.isEmpty()) {
39 return _expandedSections;
44 return _expandedSections;
47 QStringList result = _expandedSections;
48 for (
const auto &filter : _repeatFilters) {
49 bool hasDisabled =
false;
50 for (
int i = 0; i < filter.sectionNames.size(); i++) {
54 result.removeAll(filter.sectionNames[i]);
58 if (hasDisabled && !filter.disabledHeading.isEmpty()) {
59 result.append(filter.disabledHeading);
68 _ensureSectionsCached();
70 for (
auto it = _sectionKeywords.constBegin(); it != _sectionKeywords.constEnd(); ++it) {
71 map.insert(it.key(), it.value());
76void VehicleComponent::_ensureSectionsCached()
const
78 if (_sectionsCached) {
81 _sectionsCached =
true;
89 if (!file.open(QIODevice::ReadOnly)) {
90 qCWarning(VehicleComponentLog) <<
"Failed to open page definition:" << path;
94 QJsonParseError parseError;
95 const QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError);
96 if (parseError.error != QJsonParseError::NoError || !doc.isObject()) {
97 qCWarning(VehicleComponentLog) <<
"Failed to parse page definition:" << path << parseError.errorString();
100 const QJsonObject root = doc.object();
101 const QJsonObject constants = root.value(
"constants").toObject();
102 const QJsonArray sectionsArray = root.value(
"sections").toArray();
104 auto resolveConstantInt = [&](
const QString &ref) ->
int {
105 if (constants.contains(ref)) {
106 const QJsonValue v = constants.value(ref);
107 return v.isDouble() ? v.toInt() : v.toString().toInt();
113 for (
const QJsonValue &val : sectionsArray) {
114 const QJsonObject secObj = val.toObject();
115 const QString
name = secObj.value(
"title").toString();
116 if (
name.isEmpty()) {
124 const QJsonArray kwArray = secObj.value(
"keywords").toArray();
125 for (
const QJsonValue &kw : kwArray) {
126 terms.append(kw.toString());
128 for (
const QJsonValue &ctrl : secObj.value(
"controls").toArray()) {
129 const QString label = ctrl.toObject().value(
"label").toString();
130 if (!label.isEmpty()) {
134 terms.removeDuplicates();
136 const QJsonObject repeatObj = secObj.value(
"repeat").toObject();
138 const QString paramPrefix = repeatObj.value(
"paramPrefix").toString();
139 const QString probePostfix = repeatObj.value(
"probePostfix").toString();
140 const QString indexing = repeatObj.value(
"indexing").toString();
141 const int startIndex = repeatObj.value(
"startIndex").toInt(1);
142 const bool firstOmits = repeatObj.value(
"firstIndexOmitsNumber").toBool(
false);
145 const QString enableParam = repeatObj.value(
"enableParam").toString();
146 const QString disabledParamValueRef = repeatObj.value(
"disabledParamValue").toString();
147 const QJsonObject disabledSectionObj = repeatObj.value(
"disabledSection").toObject();
148 const bool hasFilter = !enableParam.isEmpty() && !disabledParamValueRef.isEmpty();
152 filter.disabledValue = resolveConstantInt(disabledParamValueRef);
153 filter.disabledHeading = disabledSectionObj.value(
"heading").toString();
157 if (indexing == QStringLiteral(
"apm_battery")) {
158 auto battPrefix = [&](
int i) -> QString {
159 if (i == 0)
return paramPrefix + QStringLiteral(
"_");
160 if (i <= 8)
return paramPrefix + QString::number(i + 1) + QStringLiteral(
"_");
161 return paramPrefix + QChar(
'A' + i - 9) + QStringLiteral(
"_");
163 auto battLabel = [](
int i) -> QString {
164 if (i <= 8)
return QString::number(i + 1);
165 return QString(QChar(
'A' + i - 9));
167 for (
int i = 0; i < 16; i++) {
168 const QString probeParam = battPrefix(i) + probePostfix;
174 _expandedSections.append(
name);
175 _sectionKeywords.insert(
name, terms);
177 filter.sectionNames.append(
name);
178 filter.paramNames.append(battPrefix(0) + enableParam);
181 for (
int i = 0; i < count; i++) {
182 const QString sectionName =
name + QStringLiteral(
" ") + battLabel(i);
183 _expandedSections.append(sectionName);
184 _sectionKeywords.insert(sectionName, terms);
186 filter.sectionNames.append(sectionName);
187 filter.paramNames.append(battPrefix(i) + enableParam);
192 for (
int i = startIndex; ; i++) {
193 const QString idx = (firstOmits && i == startIndex) ? QString() : QString::number(i);
194 const QString probeParam = paramPrefix + idx + probePostfix;
201 _expandedSections.append(
name);
202 _sectionKeywords.insert(
name, terms);
204 const QString idx = (firstOmits) ? QString() : QString::number(startIndex);
205 filter.sectionNames.append(
name);
206 filter.paramNames.append(paramPrefix + idx + enableParam);
209 for (
int i = 0; i < count; i++) {
210 const QString idx = (firstOmits && i == 0) ? QString() : QString::number(startIndex + i);
211 const QString sectionName =
name + QStringLiteral(
" ") + QString::number(startIndex + i);
212 _expandedSections.append(sectionName);
213 _sectionKeywords.insert(sectionName, terms);
215 filter.sectionNames.append(sectionName);
216 filter.paramNames.append(paramPrefix + idx + enableParam);
223 _repeatFilters.append(filter);
226 if (!_expandedSections.contains(
name)) {
227 _expandedSections.append(
name);
229 _sectionKeywords.insert(
name, terms);
237 qCWarning(VehicleComponentLog) <<
"Internal error";
241 QQmlComponent component =
new QQmlComponent(context->engine(), QUrl::fromUserInput(
"qrc:/qml/VehicleComponentSummaryButton.qml"),
this);
242 if (component.status() == QQmlComponent::Error) {
243 qCWarning(VehicleComponentLog) << component.errors();
247 QQuickItem *
const item = qobject_cast<QQuickItem*>(component.create(context));
249 qCWarning(VehicleComponentLog) <<
"Internal error";
253 item->setParentItem(parent);
254 item->setProperty(
"vehicleComponent", QVariant::fromValue(
this));
268 _ensureSectionsCached();
269 for (
const auto &filter : _repeatFilters) {
270 for (
const QString ¶mName : filter.paramNames) {
#define QGC_LOGGING_CATEGORY(name, categoryStr)
The AutoPilotPlugin class is an abstract base class which represents the methods and objects which ar...
A Fact is used to hold a single value within the system.
void valueChanged(const QVariant &value)
This signal is only meant for use by the QT property system. It should not be connected to by client ...
bool parameterExists(int componentId, const QString ¶mName) const
Fact * getParameter(int componentId, const QString ¶mName)
static constexpr int defaultComponentId
VehicleComponent(Vehicle *vehicle, AutoPilotPlugin *autopilot, AutoPilotPlugin::KnownVehicleComponent KnownVehicleComponent, QObject *parent=nullptr)
virtual ~VehicleComponent()
virtual QString vehicleConfigJson() const
Resource path to a VehicleConfig.json page definition, or empty if none.
virtual QStringList sections() const
void _triggerUpdated(QVariant)
virtual QStringList setupCompleteChangedTriggerList() const =0
virtual void setupTriggerSignals()
QVariantMap sectionKeywords() const
Search keywords per section, keyed by section title. Values are original-case translatable terms.
virtual QString name() const =0
virtual void addSummaryQmlComponent(QQmlContext *context, QQuickItem *parent)
ParameterManager * parameterManager()