QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
QGCCorePlugin.cc
Go to the documentation of this file.
1#include "QGCCorePlugin.h"
2#include "AppSettings.h"
3#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
4#include "MavlinkSettings.h"
5#endif
6#ifdef Q_OS_ANDROID
7#include "Viewer3DSettings.h"
8#ifndef QGC_NO_SERIAL_LINK
9#include "AndroidSerial.h"
10#endif
11#endif
12#include "FactMetaData.h"
13#include "QGCMAVLink.h"
15#include "InstrumentValueData.h"
16#include "JoystickManager.h"
17#include "QGCLoggingCategory.h"
18#include "QGCOptions.h"
19#include "QmlComponentInfo.h"
20#include "QmlObjectListModel.h"
21#include "SettingsManager.h"
22#include "VideoReceiver.h"
23#include "VideoBackend.h"
24#include "SurveyPlanCreator.h"
27#include "SurveyComplexItem.h"
32#include "Vehicle.h"
33#include "BlankPlanCreator.h"
34#include "ComplexMissionItem.h"
36
37#ifdef QGC_CUSTOM_BUILD
38#include CUSTOMHEADER
39#endif
40
41#include <QtCore/QApplicationStatic>
42#include <QtCore/QFile>
43#include <QtQml/QQmlApplicationEngine>
44#include <QtQml/QQmlContext>
45#include <QtQuick/QQuickItem>
46
47QGC_LOGGING_CATEGORY(QGCCorePluginLog, "API.QGCCorePlugin");
48
49#ifndef QGC_CUSTOM_BUILD
50Q_APPLICATION_STATIC(QGCCorePlugin, _qgcCorePluginInstance);
51#endif
52
54 : QObject(parent)
55 , _defaultOptions(new QGCOptions(this))
56 , _emptyCustomMapItems(new QmlObjectListModel(this))
57{
58 qCDebug(QGCCorePluginLog) << this;
59}
60
62{
63 qCDebug(QGCCorePluginLog) << this;
64}
65
67{
68#ifndef QGC_CUSTOM_BUILD
69 return _qgcCorePluginInstance();
70#else
71 return CUSTOMCLASS::instance();
72#endif
73}
74
75const QVariantList &QGCCorePlugin::analyzePages()
76{
77 // Log Viewer is excluded on mobile (Android/iOS) because parsing large log files
78 // (e.g. 900 MB ULog files with 1000+ fields) exhausts the mobile heap, causing
79 // OOM crashes. Proper mobile support requires time-bucketed downsampling and will
80 // be addressed in a future major release.
81#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
82 static const QVariantList analyzeList = {
83#else
84 static const QVariantList analyzeList = {
85 QVariant::fromValue(new QmlComponentInfo(
86 tr("Log Viewer"),
87 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/LogViewer/LogViewerPage.qml")),
88 QUrl::fromUserInput(QStringLiteral("qrc:/qmlimages/MAVLinkInspector.svg")))),
89#endif
90 QVariant::fromValue(new QmlComponentInfo(
91 tr("Onboard Logs"),
92 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/OnboardLogs/OnboardLogPage.qml")),
93 QUrl::fromUserInput(QStringLiteral("qrc:/qmlimages/OnboardLogIcon.svg")),
94 nullptr, true /* requiresVehicle */)),
95 QVariant::fromValue(new QmlComponentInfo(
96 tr("GeoTag Images"),
97 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/GeoTag/GeoTagPage.qml")),
98 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/GeoTag/GeoTagIcon.svg")))),
99 QVariant::fromValue(new QmlComponentInfo(
100 tr("MAVLink Console"),
101 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/MAVLinkConsole/MAVLinkConsolePage.qml")),
102 QUrl::fromUserInput(QStringLiteral("qrc:/qmlimages/MAVLinkConsoleIcon.svg")),
103 nullptr, true /* requiresVehicle */)),
104 QVariant::fromValue(new QmlComponentInfo(
105 tr("MAVLink Inspector"),
106 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/MAVLinkInspector/MAVLinkInspectorPage.qml")),
107 QUrl::fromUserInput(QStringLiteral("qrc:/qmlimages/MAVLinkInspector.svg")),
108 nullptr, true /* requiresVehicle */)),
109 QVariant::fromValue(new QmlComponentInfo(
110 tr("Vibration"),
111 QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/AnalyzeView/Vibration/VibrationPage.qml")),
112 QUrl::fromUserInput(QStringLiteral("qrc:/qmlimages/VibrationPageIcon")),
113 nullptr, true /* requiresVehicle */)),
114 };
115
116 return analyzeList;
117}
118
120{
121 return _defaultOptions;
122}
123
125{
126 return _emptyCustomMapItems;
127}
128
129void QGCCorePlugin::adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
130{
131#ifdef Q_OS_ANDROID
132 // 3D view rendering is too flaky on Android GPUs/drivers; force the
133 // feature off. Hiding the setting also forces it to its default value
134 // (false) regardless of any previously saved user setting.
135 if ((settingsGroup == Viewer3DSettings::settingsGroup) && (metaData.name() == Viewer3DSettings::enabledName)) {
136 userVisible = false;
137 return;
138 }
139#endif
140
141 if (settingsGroup == AppSettings::settingsGroup) {
142 if (metaData.name() == AppSettings::indoorPaletteName) {
143 QVariant outdoorPalette;
144#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
145 outdoorPalette = 0;
146#else
147 outdoorPalette = 1;
148#endif
149 metaData.setRawDefaultValue(outdoorPalette);
150 return;
151 }
152#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
153 else if (metaData.name() == MavlinkSettings::telemetrySaveName) {
154 metaData.setRawDefaultValue(false);
155 return;
156 }
157#endif
158#ifndef Q_OS_ANDROID
159 else if (metaData.name() == AppSettings::androidDontSaveToSDCardName) {
160 userVisible = false;
161 return;
162 }
163#endif
164 else if (metaData.name() == AppSettings::androidUsePosixSerialName) {
165#if defined(Q_OS_ANDROID) && !defined(QGC_NO_SERIAL_LINK)
166 // Only show when the device actually exposes accessible serial device nodes
168#else
169 userVisible = false;
170#endif
171 return;
172 }
173 }
174}
175
177{
178 return tr("WARNING: You are about to enter Advanced Mode. "
179 "If used incorrectly, this may cause your vehicle to malfunction thus voiding your warranty. "
180 "You should do so only if instructed by customer support. "
181 "Are you sure you want to enable Advanced Mode?");
182}
183
185{
186#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
188#else
190#endif
191
192 if (factValueGrid->specificVehicleForCard()) {
193 bool includeFWValues = factValueGrid->vehicleClass() == QGCMAVLink::VehicleClassFixedWing || factValueGrid->vehicleClass() == QGCMAVLink::VehicleClassVTOL || factValueGrid->vehicleClass() == QGCMAVLink::VehicleClassAirship;
194
195 factValueGrid->setFontSize(defaultFontSize);
196 factValueGrid->appendColumn();
197 factValueGrid->appendColumn();
198
199 int rowIndex = 0;
200 int colIndex = 0;
201
202 // first cell
203 QmlObjectListModel* column = factValueGrid->columns()->value<QmlObjectListModel*>(colIndex++);
204 InstrumentValueData* value = column->value<InstrumentValueData*>(rowIndex);
205 value->setFact("Vehicle", "AltitudeRelative");
206 value->setIcon("arrow-thick-up.svg");
207 value->setText(value->fact()->shortDescription());
208 value->setShowUnits(true);
209
210 // second cell
211 column = factValueGrid->columns()->value<QmlObjectListModel*>(colIndex++);
212 value = column->value<InstrumentValueData*>(rowIndex);
213 if (includeFWValues) {
214 value->setFact("Vehicle", "AirSpeed");
215 value->setText("AirSpd");
216 value->setShowUnits(true);
217 } else {
218 value->setFact("Vehicle", "GroundSpeed");
219 value->setIcon("arrow-simple-right.svg");
220 value->setText(value->fact()->shortDescription());
221 value->setShowUnits(true);
222 }
223 } else {
224 const bool includeFWValues = ((factValueGrid->vehicleClass() == QGCMAVLink::VehicleClassFixedWing) || (factValueGrid->vehicleClass() == QGCMAVLink::VehicleClassVTOL) || (factValueGrid->vehicleClass() == QGCMAVLink::VehicleClassAirship));
225
226 factValueGrid->setFontSize(defaultFontSize);
227
228 (void) factValueGrid->appendColumn();
229 (void) factValueGrid->appendColumn();
230 (void) factValueGrid->appendColumn();
231 if (includeFWValues) {
232 (void) factValueGrid->appendColumn();
233 }
234 factValueGrid->appendRow();
235
236 int rowIndex = 0;
237 QmlObjectListModel *column = factValueGrid->columns()->value<QmlObjectListModel*>(0);
238
239 InstrumentValueData *value = column->value<InstrumentValueData*>(rowIndex++);
240 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("AltitudeRelative"));
241 value->setIcon(QStringLiteral("arrow-thick-up.svg"));
242 value->setText(value->fact()->shortDescription());
243 value->setShowUnits(true);
244
245 value = column->value<InstrumentValueData*>(rowIndex++);
246 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("DistanceToHome"));
247 value->setIcon(QStringLiteral("bookmark copy 3.svg"));
248 value->setText(value->fact()->shortDescription());
249 value->setShowUnits(true);
250
251 rowIndex = 0;
252 column = factValueGrid->columns()->value<QmlObjectListModel*>(1);
253
254 value = column->value<InstrumentValueData*>(rowIndex++);
255 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("ClimbRate"));
256 value->setIcon(QStringLiteral("arrow-simple-up.svg"));
257 value->setText(value->fact()->shortDescription());
258 value->setShowUnits(true);
259
260 value = column->value<InstrumentValueData*>(rowIndex++);
261 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("GroundSpeed"));
262 value->setIcon(QStringLiteral("arrow-simple-right.svg"));
263 value->setText(value->fact()->shortDescription());
264 value->setShowUnits(true);
265
266 if (includeFWValues) {
267 rowIndex = 0;
268 column = factValueGrid->columns()->value<QmlObjectListModel*>(2);
269
270 value = column->value<InstrumentValueData*>(rowIndex++);
271 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("AirSpeed"));
272 value->setText(QStringLiteral("AirSpd"));
273 value->setShowUnits(true);
274
275 value = column->value<InstrumentValueData*>(rowIndex++);
276 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("ThrottlePct"));
277 value->setText(QStringLiteral("Thr"));
278 value->setShowUnits(true);
279 }
280
281 rowIndex = 0;
282 column = factValueGrid->columns()->value<QmlObjectListModel*>(includeFWValues ? 3 : 2);
283
284 value = column->value<InstrumentValueData*>(rowIndex++);
285 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("FlightTime"));
286 value->setIcon(QStringLiteral("timer.svg"));
287 value->setText(value->fact()->shortDescription());
288 value->setShowUnits(false);
289
290 value = column->value<InstrumentValueData*>(rowIndex++);
291 value->setFact(QStringLiteral("Vehicle"), QStringLiteral("FlightDistance"));
292 value->setIcon(QStringLiteral("travel-walk.svg"));
293 value->setText(value->fact()->shortDescription());
294 value->setShowUnits(true);
295 }
296}
297
298QQmlApplicationEngine *QGCCorePlugin::createQmlApplicationEngine(QObject *parent)
299{
300 QQmlApplicationEngine *const qmlEngine = new QQmlApplicationEngine(parent);
301 qmlEngine->addImportPath(QStringLiteral("qrc:/qml"));
302 qmlEngine->rootContext()->setContextProperty(QStringLiteral("joystickManager"), JoystickManager::instance());
303 return qmlEngine;
304}
305
306void QGCCorePlugin::destroyQmlApplicationEngine(QQmlApplicationEngine *qmlEngine)
307{
308 delete qmlEngine;
309}
310
311void QGCCorePlugin::createRootWindow(QQmlApplicationEngine *qmlEngine)
312{
313 qmlEngine->load(QUrl(QStringLiteral("qrc:/qml/QGroundControl/MainWindow.qml")));
314}
315
320
321void *QGCCorePlugin::createVideoSink(QQuickItem *widget, QObject *parent)
322{
323 return VideoBackend::createSink(widget, parent);
324}
325
327{
329}
330
332{
333 static const QVariantList toolBarIndicatorList = QVariantList(
334 {
335 QVariant::fromValue(QUrl::fromUserInput(QStringLiteral("qrc:/qml/QGroundControl/Toolbar/RTKGPSIndicator.qml"))),
336 }
337 );
338
339 return toolBarIndicatorList;
340}
341
343{
344 QList<int> rgIdsToShow;
345
346 rgIdsToShow.append(firstRunPromptStdIds());
347 rgIdsToShow.append(firstRunPromptCustomIds());
348
349 const QList<int> rgAlreadyShownIds = AppSettings::firstRunPromptsIdsVariantToList(SettingsManager::instance()->appSettings()->firstRunPromptIdsShown()->rawValue());
350 for (int idToRemove: rgAlreadyShownIds) {
351 (void) rgIdsToShow.removeOne(idToRemove);
352 }
353
354 QVariantList rgVarIdsToShow;
355 for (int id: rgIdsToShow) {
356 rgVarIdsToShow.append(id);
357 }
358
359 return rgVarIdsToShow;
360}
361
363{
364 switch (id) {
366 return QStringLiteral("/qml/QGroundControl/FirstRunPromptDialogs/InitialSetupPrompt.qml");
367 default:
368 return QString();
369 }
370}
371
372void QGCCorePlugin::_setShowTouchAreas(bool show)
373{
374 if (show != _showTouchAreas) {
375 _showTouchAreas = show;
376 emit showTouchAreasChanged(show);
377 }
378}
379
380void QGCCorePlugin::_setShowAdvancedUI(bool show)
381{
382 if (show != _showAdvancedUI) {
383 _showAdvancedUI = show;
384 emit showAdvancedUIChanged(show);
385 }
386}
387
389{
390 auto makeEntry = [](const char* canonical, const QString& translated) {
391 QVariantMap entry;
392 entry[QStringLiteral("canonicalName")] = QString(canonical);
393 entry[QStringLiteral("translatedName")] = translated;
394 return entry;
395 };
396
397 QVariantList items;
398 items.append(makeEntry(SurveyComplexItem::canonicalName, SurveyComplexItem::tr(SurveyComplexItem::canonicalName)));
399 items.append(makeEntry(CorridorScanComplexItem::canonicalName, CorridorScanComplexItem::tr(CorridorScanComplexItem::canonicalName)));
400 if (vehicle->multiRotor() || vehicle->vtol()) {
401 items.append(makeEntry(StructureScanComplexItem::canonicalName, StructureScanComplexItem::tr(StructureScanComplexItem::canonicalName)));
402 }
403 // Note: Landing pattern items are not added here — they have their own dedicated button
404 return items;
405}
406
407QList<PlanCreator*> QGCCorePlugin::planCreators(PlanMasterController *planMasterController)
408{
409 return {
410 new SurveyPlanCreator(planMasterController),
411 new CorridorScanPlanCreator(planMasterController),
412 new StructureScanPlanCreator(planMasterController),
413 new BlankPlanCreator(planMasterController),
414 };
415}
416
418 const QString &complexItemType,
419 PlanMasterController *masterController,
420 bool flyView,
421 const QString &kmlOrShpFile)
422{
423 if (complexItemType == SurveyComplexItem::canonicalName || complexItemType == SurveyComplexItem::jsonComplexItemTypeValue) {
424 return new SurveyComplexItem(masterController, flyView, kmlOrShpFile);
425 } else if (complexItemType == CorridorScanComplexItem::canonicalName || complexItemType == CorridorScanComplexItem::jsonComplexItemTypeValue) {
426 return new CorridorScanComplexItem(masterController, flyView, kmlOrShpFile);
427 } else if (complexItemType == StructureScanComplexItem::canonicalName || complexItemType == StructureScanComplexItem::jsonComplexItemTypeValue) {
428 return new StructureScanComplexItem(masterController, flyView, kmlOrShpFile);
430 return new FixedWingLandingComplexItem(masterController, flyView);
431 } else if (complexItemType == VTOLLandingComplexItem::canonicalName || complexItemType == VTOLLandingComplexItem::jsonComplexItemTypeValue) {
432 return new VTOLLandingComplexItem(masterController, flyView);
433 }
434
435 qCWarning(QGCCorePluginLog) << "QGCCorePlugin::createComplexMissionItem - Unknown complex item type:" << complexItemType;
436 return nullptr;
437}
Q_APPLICATION_STATIC(QGCCorePlugin, _qgcCorePluginInstance)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
static QList< int > firstRunPromptsIdsVariantToList(const QVariant &firstRunPromptIds)
static constexpr const char * canonicalName
static constexpr const char * jsonComplexItemTypeValue
Holds the meta data associated with a Fact.
void setRawDefaultValue(const QVariant &rawDefaultValue)
QString name() const
QmlObjectListModel * columns(void) const
void setFontSize(FontSize fontSize)
Q_INVOKABLE QmlObjectListModel * appendColumn(void)
Vehicle * specificVehicleForCard(void) const
QGCMAVLinkTypes::VehicleClass_t vehicleClass(void) const
Q_INVOKABLE void appendRow(void)
static constexpr const char * jsonComplexItemTypeValue
static constexpr const char * canonicalName
Q_INVOKABLE void setFact(const QString &factGroupName, const QString &factName)
static JoystickManager * instance()
Master controller for mission, fence, rally.
Extension mechanism for generic, non-firmware-specific customization of QGC.
virtual ComplexMissionItem * createComplexMissionItem(const QString &complexItemType, PlanMasterController *masterController, bool flyView, const QString &kmlOrShpFile=QString())
QGCCorePlugin(QObject *parent=nullptr)
virtual QVariantList complexMissionItemNames(Vehicle *vehicle)
void showTouchAreasChanged(bool showTouchAreas)
virtual ~QGCCorePlugin()
virtual void * createVideoSink(QQuickItem *widget, QObject *parent)
Allows the plugin to override the creation of VideoSink.
virtual void factValueGridCreateDefaultSettings(FactValueGrid *factValueGrid)
void showAdvancedUIChanged(bool showAdvancedUI)
virtual QList< int > firstRunPromptStdIds()
virtual const QVariantList & toolBarIndicators()
virtual QList< int > firstRunPromptCustomIds()
virtual Q_INVOKABLE QString firstRunPromptResource(int id) const
Returns the resource which contains the specified first run prompt for display.
static constexpr int kInitialSetupPromptId
virtual QGCOptions * options()
virtual QQmlApplicationEngine * createQmlApplicationEngine(QObject *parent)
virtual const QVariantList & analyzePages()
virtual QString showAdvancedUIMessage() const
virtual void createRootWindow(QQmlApplicationEngine *qmlEngine)
Allows the plugin to override the creation of the root (native) window.
virtual VideoReceiver * createVideoReceiver(QObject *parent)
Allows the plugin to override the creation of VideoReceiver.
virtual void releaseVideoSink(void *sink)
Allows the plugin to override the release of VideoSink.
Q_INVOKABLE QVariantList firstRunPromptsToShow()
Returns the list of first run prompt ids which need to be displayed according to current settings.
virtual const QmlObjectListModel * customMapItems()
Allows custom builds to add custom items to the FlightMap. Objects put into QmlObjectListModel should...
virtual QList< PlanCreator * > planCreators(PlanMasterController *planMasterController)
virtual void adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible)
virtual void destroyQmlApplicationEngine(QQmlApplicationEngine *qmlEngine)
static QGCCorePlugin * instance()
Represents a Qml component which can be loaded from a resource.
T value(int index) const
QString settingsGroup() const
static SettingsManager * instance()
static constexpr const char * canonicalName
static constexpr const char * jsonComplexItemTypeValue
static constexpr const char * jsonComplexItemTypeValue
static constexpr const char * canonicalName
static constexpr const char * canonicalName
static constexpr const char * jsonComplexItemTypeValue
bool vtol() const
Definition Vehicle.cc:1757
bool multiRotor() const
Definition Vehicle.cc:1752
bool hasPosixSerialPorts()
void releaseSink(void *sink)
void * createSink(QQuickItem *widget, QObject *parent)
VideoReceiver * createReceiver(QObject *parent)