QGCCorePlugin.cc 17.4 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

10
#include "QGCApplication.h"
11 12
#include "QGCCorePlugin.h"
#include "QGCOptions.h"
13
#include "QmlComponentInfo.h"
14
#include "FactMetaData.h"
Don Gagne's avatar
Don Gagne committed
15
#include "SettingsManager.h"
16
#include "AppMessages.h"
17
#include "QmlObjectListModel.h"
18
#include "VideoManager.h"
19 20
#if defined(QGC_GST_STREAMING)
#include "GStreamer.h"
21
#include "VideoReceiver.h"
22
#endif
23
#include "QGCLoggingCategory.h"
24
#include "QGCCameraManager.h"
25
#include "HorizontalFactValueGrid.h"
26
#include "InstrumentValueData.h"
27 28 29 30 31 32

#include <QtQml>
#include <QQmlEngine>

/// @file
///     @brief Core Plugin Interface for QGroundControl - Default Implementation
Gus Grubba's avatar
Gus Grubba committed
33
///     @author Gus Grubba <gus@auterion.com>
34 35 36 37 38 39 40

class QGCCorePlugin_p
{
public:
    QGCCorePlugin_p()
    {
    }
41

42 43 44 45 46 47 48 49
    ~QGCCorePlugin_p()
    {
        if(pGeneral)
            delete pGeneral;
        if(pCommLinks)
            delete pCommLinks;
        if(pOfflineMaps)
            delete pOfflineMaps;
50 51 52 53
#if defined(QGC_GST_TAISYNC_ENABLED)
        if(pTaisync)
            delete pTaisync;
#endif
54 55 56 57
#if defined(QGC_GST_MICROHARD_ENABLED)
        if(pMicrohard)
            delete pMicrohard;
#endif
Gus Grubba's avatar
Gus Grubba committed
58
#if defined(QGC_AIRMAP_ENABLED)
Gus Grubba's avatar
Gus Grubba committed
59 60
        if(pAirmap)
            delete pAirmap;
Gus Grubba's avatar
Gus Grubba committed
61
#endif
62 63 64 65 66 67 68 69 70
        if(pMAVLink)
            delete pMAVLink;
        if(pConsole)
            delete pConsole;
#if defined(QT_DEBUG)
        if(pMockLink)
            delete pMockLink;
        if(pDebug)
            delete pDebug;
71 72
        if(pQmlTest)
            delete pQmlTest;
73 74 75 76
#endif
        if(defaultOptions)
            delete defaultOptions;
    }
77

78 79 80 81 82 83
    QmlComponentInfo* pGeneral                  = nullptr;
    QmlComponentInfo* pCommLinks                = nullptr;
    QmlComponentInfo* pOfflineMaps              = nullptr;
#if defined(QGC_GST_TAISYNC_ENABLED)
    QmlComponentInfo* pTaisync                  = nullptr;
#endif
84 85 86
#if defined(QGC_GST_MICROHARD_ENABLED)
    QmlComponentInfo* pMicrohard                = nullptr;
#endif
Gus Grubba's avatar
Gus Grubba committed
87
#if defined(QGC_AIRMAP_ENABLED)
88
    QmlComponentInfo* pAirmap                   = nullptr;
Gus Grubba's avatar
Gus Grubba committed
89
#endif
90 91 92
    QmlComponentInfo* pMAVLink                  = nullptr;
    QmlComponentInfo* pConsole                  = nullptr;
    QmlComponentInfo* pHelp                     = nullptr;
93
#if defined(QT_DEBUG)
94 95
    QmlComponentInfo* pMockLink                 = nullptr;
    QmlComponentInfo* pDebug                    = nullptr;
96
    QmlComponentInfo* pQmlTest                  = nullptr;
97
#endif
98

99 100
    QGCOptions*         defaultOptions          = nullptr;
    QVariantList        settingsList;
101
    QVariantList        analyzeList;
102 103

    QmlObjectListModel _emptyCustomMapItems;
104 105 106 107 108 109 110 111 112
};

QGCCorePlugin::~QGCCorePlugin()
{
    if(_p) {
        delete _p;
    }
}

113 114
QGCCorePlugin::QGCCorePlugin(QGCApplication *app, QGCToolbox* toolbox)
    : QGCTool(app, toolbox)
115
    , _showTouchAreas(false)
116
    , _showAdvancedUI(true)
117
{
118
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
119 120 121 122 123
    _p = new QGCCorePlugin_p;
}

void QGCCorePlugin::setToolbox(QGCToolbox *toolbox)
{
DonLakeFlyer's avatar
DonLakeFlyer committed
124
    QGCTool::setToolbox(toolbox);
125 126 127 128

    qmlRegisterUncreatableType<QGCCorePlugin>       ("QGroundControl", 1, 0, "QGCCorePlugin",       "Reference only");
    qmlRegisterUncreatableType<QGCOptions>          ("QGroundControl", 1, 0, "QGCOptions",          "Reference only");
    qmlRegisterUncreatableType<QGCFlyViewOptions>   ("QGroundControl", 1, 0, "QGCFlyViewOptions",   "Reference only");
129 130
}

131
QVariantList &QGCCorePlugin::settingsPages()
132 133
{
    if(!_p->pGeneral) {
134
        _p->pGeneral = new QmlComponentInfo(tr("General"),
135 136
                                            QUrl::fromUserInput("qrc:/qml/GeneralSettings.qml"),
                                            QUrl::fromUserInput("qrc:/res/gear-white.svg"));
137
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pGeneral)));
138
        _p->pCommLinks = new QmlComponentInfo(tr("Comm Links"),
139 140
                                              QUrl::fromUserInput("qrc:/qml/LinkSettings.qml"),
                                              QUrl::fromUserInput("qrc:/res/waves.svg"));
141
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pCommLinks)));
142
        _p->pOfflineMaps = new QmlComponentInfo(tr("Offline Maps"),
143 144
                                                QUrl::fromUserInput("qrc:/qml/OfflineMap.qml"),
                                                QUrl::fromUserInput("qrc:/res/waves.svg"));
145
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pOfflineMaps)));
146 147
#if defined(QGC_GST_TAISYNC_ENABLED)
        _p->pTaisync = new QmlComponentInfo(tr("Taisync"),
148 149
                                            QUrl::fromUserInput("qrc:/qml/TaisyncSettings.qml"),
                                            QUrl::fromUserInput(""));
150 151
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pTaisync)));
#endif
152 153
#if defined(QGC_GST_MICROHARD_ENABLED)
        _p->pMicrohard = new QmlComponentInfo(tr("Microhard"),
154 155
                                              QUrl::fromUserInput("qrc:/qml/MicrohardSettings.qml"),
                                              QUrl::fromUserInput(""));
156 157
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pMicrohard)));
#endif
Gus Grubba's avatar
Gus Grubba committed
158
#if defined(QGC_AIRMAP_ENABLED)
Gus Grubba's avatar
Gus Grubba committed
159
        _p->pAirmap = new QmlComponentInfo(tr("AirMap"),
160 161
                                           QUrl::fromUserInput("qrc:/qml/AirmapSettings.qml"),
                                           QUrl::fromUserInput(""));
162
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pAirmap)));
Gus Grubba's avatar
Gus Grubba committed
163
#endif
164
        _p->pMAVLink = new QmlComponentInfo(tr("MAVLink"),
165 166
                                            QUrl::fromUserInput("qrc:/qml/MavlinkSettings.qml"),
                                            QUrl::fromUserInput("qrc:/res/waves.svg"));
167
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pMAVLink)));
168
        _p->pConsole = new QmlComponentInfo(tr("Console"),
169
                                            QUrl::fromUserInput("qrc:/qml/QGroundControl/Controls/AppMessages.qml"));
170
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pConsole)));
171
        _p->pHelp = new QmlComponentInfo(tr("Help"),
172
                                         QUrl::fromUserInput("qrc:/qml/HelpSettings.qml"));
173
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pHelp)));
DonLakeFlyer's avatar
DonLakeFlyer committed
174
#if defined(QT_DEBUG)
175
        //-- These are always present on Debug builds
176
        _p->pMockLink = new QmlComponentInfo(tr("Mock Link"),
177
                                             QUrl::fromUserInput("qrc:/qml/MockLink.qml"));
178
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pMockLink)));
179
        _p->pDebug = new QmlComponentInfo(tr("Debug"),
180
                                          QUrl::fromUserInput("qrc:/qml/DebugWindow.qml"));
181
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pDebug)));
182
        _p->pQmlTest = new QmlComponentInfo(tr("Palette Test"),
183
                                            QUrl::fromUserInput("qrc:/qml/QmlTest.qml"));
184
        _p->settingsList.append(QVariant::fromValue(reinterpret_cast<QmlComponentInfo*>(_p->pQmlTest)));
DonLakeFlyer's avatar
DonLakeFlyer committed
185
#endif
186 187 188 189
    }
    return _p->settingsList;
}

190 191 192
QVariantList& QGCCorePlugin::analyzePages()
{
    if (!_p->analyzeList.count()) {
DonLakeFlyer's avatar
DonLakeFlyer committed
193
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("Log Download"),     QUrl::fromUserInput("qrc:/qml/LogDownloadPage.qml"),        QUrl::fromUserInput("qrc:/qmlimages/LogDownloadIcon"))));
194
#if !defined(__mobile__)
DonLakeFlyer's avatar
DonLakeFlyer committed
195
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("GeoTag Images"),    QUrl::fromUserInput("qrc:/qml/GeoTagPage.qml"),             QUrl::fromUserInput("qrc:/qmlimages/GeoTagIcon"))));
196
#endif
DonLakeFlyer's avatar
DonLakeFlyer committed
197
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("MAVLink Console"),  QUrl::fromUserInput("qrc:/qml/MavlinkConsolePage.qml"),     QUrl::fromUserInput("qrc:/qmlimages/MavlinkConsoleIcon"))));
198
#if defined(QGC_ENABLE_MAVLINK_INSPECTOR)
DonLakeFlyer's avatar
DonLakeFlyer committed
199
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("MAVLink Inspector"),QUrl::fromUserInput("qrc:/qml/MAVLinkInspectorPage.qml"),   QUrl::fromUserInput("qrc:/qmlimages/MAVLinkInspector"))));
200
#endif
DonLakeFlyer's avatar
DonLakeFlyer committed
201
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("Vibration"),        QUrl::fromUserInput("qrc:/qml/VibrationPage.qml"),          QUrl::fromUserInput("qrc:/qmlimages/VibrationPageIcon"))));
202 203 204 205
    }
    return _p->analyzeList;
}

206
int QGCCorePlugin::defaultSettings()
207 208 209 210
{
    return 0;
}

211 212
QGCOptions* QGCCorePlugin::options()
{
213 214
    if (!_p->defaultOptions) {
        _p->defaultOptions = new QGCOptions(this);
215 216 217 218
    }
    return _p->defaultOptions;
}

219 220 221
bool QGCCorePlugin::overrideSettingsGroupVisibility(QString name)
{
    Q_UNUSED(name);
222

223 224 225
    // Always show all
    return true;
}
226

227
bool QGCCorePlugin::adjustSettingMetaData(const QString& settingsGroup, FactMetaData& metaData)
228
{
229
    if (settingsGroup == AppSettings::settingsGroup) {
Gus Grubba's avatar
Gus Grubba committed
230 231 232 233 234 235 236 237
#if !defined(QGC_ENABLE_PAIRING)
        //-- If we don't support pairing, disable it.
        if (metaData.name() == AppSettings::usePairingName) {
            metaData.setRawDefaultValue(false);
            //-- And hide the option
            return false;
        }
#endif
238

239 240 241
        //-- Default Palette
        if (metaData.name() == AppSettings::indoorPaletteName) {
            QVariant outdoorPalette;
Don Gagne's avatar
Don Gagne committed
242
#if defined (__mobile__)
243
            outdoorPalette = 0;
Don Gagne's avatar
Don Gagne committed
244
#else
245
            outdoorPalette = 1;
Don Gagne's avatar
Don Gagne committed
246
#endif
247 248 249 250
            metaData.setRawDefaultValue(outdoorPalette);
            return true;
        }

251
#if defined (__mobile__)
252 253 254 255 256
        if (metaData.name() == AppSettings::telemetrySaveName) {
            // Mobile devices have limited storage so don't turn on telemtry saving by default
            metaData.setRawDefaultValue(false);
            return true;
        }
257
#endif
Don Gagne's avatar
Don Gagne committed
258
    }
259

260
    return true; // Show setting in ui
261
}
DonLakeFlyer's avatar
DonLakeFlyer committed
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277

void QGCCorePlugin::setShowTouchAreas(bool show)
{
    if (show != _showTouchAreas) {
        _showTouchAreas = show;
        emit showTouchAreasChanged(show);
    }
}

void QGCCorePlugin::setShowAdvancedUI(bool show)
{
    if (show != _showAdvancedUI) {
        _showAdvancedUI = show;
        emit showAdvancedUIChanged(show);
    }
}
278

279
void QGCCorePlugin::paletteOverride(QString /*colorName*/, QGCPalette::PaletteColorInfo_t& /*colorInfo*/)
280
{
281

282
}
283

284
QString QGCCorePlugin::showAdvancedUIMessage() const
285 286 287 288 289 290
{
    return tr("WARNING: You are about to enter Advanced Mode. "
              "If used incorrectly, this may cause your vehicle to malfunction thus voiding your warranty. "
              "You should do so only if instructed by customer support. "
              "Are you sure you want to enable Advanced Mode?");
}
291

292
void QGCCorePlugin::factValueGridCreateDefaultSettings(const QString& defaultSettingsGroup)
293
{
294
    HorizontalFactValueGrid factValueGrid(defaultSettingsGroup);
295

296
    bool        includeFWValues = factValueGrid.vehicleClass() == QGCMAVLink::VehicleClassFixedWing || factValueGrid.vehicleClass() == QGCMAVLink::VehicleClassVTOL;
297

298
    factValueGrid.setFontSize(FactValueGrid::LargeFontSize);
299

300
    factValueGrid.appendColumn();
301 302 303 304 305
    factValueGrid.appendColumn();
    factValueGrid.appendColumn();
    if (includeFWValues) {
        factValueGrid.appendColumn();
    }
306
    factValueGrid.appendRow();
307

308 309
    int                 rowIndex    = 0;
    QmlObjectListModel* column      = factValueGrid.columns()->value<QmlObjectListModel*>(0);
310

311
    InstrumentValueData* value = column->value<InstrumentValueData*>(rowIndex++);
312 313 314 315 316
    value->setFact("Vehicle", "AltitudeRelative");
    value->setIcon("arrow-thick-up.svg");
    value->setText(value->fact()->shortDescription());
    value->setShowUnits(true);

317 318 319
    value = column->value<InstrumentValueData*>(rowIndex++);
    value->setFact("Vehicle", "DistanceToHome");
    value->setIcon("bookmark copy 3.svg");
320 321 322
    value->setText(value->fact()->shortDescription());
    value->setShowUnits(true);

323 324
    rowIndex    = 0;
    column      = factValueGrid.columns()->value<QmlObjectListModel*>(1);
325

326 327 328
    value = column->value<InstrumentValueData*>(rowIndex++);
    value->setFact("Vehicle", "ClimbRate");
    value->setIcon("arrow-simple-up.svg");
329 330 331
    value->setText(value->fact()->shortDescription());
    value->setShowUnits(true);

332
    value = column->value<InstrumentValueData*>(rowIndex++);
333 334 335 336 337
    value->setFact("Vehicle", "GroundSpeed");
    value->setIcon("arrow-simple-right.svg");
    value->setText(value->fact()->shortDescription());
    value->setShowUnits(true);

338

339
    if (includeFWValues) {
340 341 342 343 344 345 346 347 348
        rowIndex    = 0;
        column      = factValueGrid.columns()->value<QmlObjectListModel*>(2);

        value = column->value<InstrumentValueData*>(rowIndex++);
        value->setFact("Vehicle", "AirSpeed");
        value->setText("AirSpd");
        value->setShowUnits(true);

        value = column->value<InstrumentValueData*>(rowIndex++);
349 350
        value->setFact("Vehicle", "ThrottlePct");
        value->setText("Thr");
351
        value->setShowUnits(true);
352
    }
353

354 355 356 357 358 359 360 361 362 363
    rowIndex    = 0;
    column      = factValueGrid.columns()->value<QmlObjectListModel*>(includeFWValues ? 3 : 2);

    value = column->value<InstrumentValueData*>(rowIndex++);
    value->setFact("Vehicle", "FlightTime");
    value->setIcon("timer.svg");
    value->setText(value->fact()->shortDescription());
    value->setShowUnits(false);

    value = column->value<InstrumentValueData*>(rowIndex++);
364 365 366 367
    value->setFact("Vehicle", "FlightDistance");
    value->setIcon("travel-walk.svg");
    value->setText(value->fact()->shortDescription());
    value->setShowUnits(true);
368
}
369

370
QQmlApplicationEngine* QGCCorePlugin::createQmlApplicationEngine(QObject* parent)
371
{
372 373 374 375 376 377 378 379 380 381
    QQmlApplicationEngine* qmlEngine = new QQmlApplicationEngine(parent);
    qmlEngine->addImportPath("qrc:/qml");
    qmlEngine->rootContext()->setContextProperty("joystickManager", qgcApp()->toolbox()->joystickManager());
    qmlEngine->rootContext()->setContextProperty("debugMessageModel", AppMessages::getModel());
    return qmlEngine;
}

void QGCCorePlugin::createRootWindow(QQmlApplicationEngine* qmlEngine)
{
    qmlEngine->load(QUrl(QStringLiteral("qrc:/qml/MainRootWindow.qml")));
382
}
383 384 385 386 387 388 389 390 391

bool QGCCorePlugin::mavlinkMessage(Vehicle* vehicle, LinkInterface* link, mavlink_message_t message)
{
    Q_UNUSED(vehicle);
    Q_UNUSED(link);
    Q_UNUSED(message);

    return true;
}
392

393
QmlObjectListModel* QGCCorePlugin::customMapItems()
394 395 396
{
    return &_p->_emptyCustomMapItems;
}
397

398 399 400 401 402
VideoManager* QGCCorePlugin::createVideoManager(QGCApplication *app, QGCToolbox *toolbox)
{
    return new VideoManager(app, toolbox);
}

403 404
VideoReceiver* QGCCorePlugin::createVideoReceiver(QObject* parent)
{
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
#if defined(QGC_GST_STREAMING)
    return GStreamer::createVideoReceiver(parent);
#else
    Q_UNUSED(parent)
    return nullptr;
#endif
}

void* QGCCorePlugin::createVideoSink(QObject* parent, QQuickItem* widget)
{
#if defined(QGC_GST_STREAMING)
    return GStreamer::createVideoSink(parent, widget);
#else
    Q_UNUSED(parent)
    Q_UNUSED(widget)
    return nullptr;
#endif
422
}
423

424 425 426 427 428 429 430 431 432
void QGCCorePlugin::releaseVideoSink(void* sink)
{
#if defined(QGC_GST_STREAMING)
    GStreamer::releaseVideoSink(sink);
#else
    Q_UNUSED(sink)
#endif
}

433
bool QGCCorePlugin::guidedActionsControllerLogging() const
434 435 436
{
    return GuidedActionsControllerLog().isDebugEnabled();
}
437

438
QString QGCCorePlugin::stableVersionCheckFileUrl() const
439 440 441 442 443 444 445 446
{
#ifdef QGC_CUSTOM_BUILD
    // Custom builds must override to turn on and provide their own location
    return QString();
#else
    return QString("https://s3-us-west-2.amazonaws.com/qgroundcontrol/latest/QGC.version.txt");
#endif
}
447

448
const QVariantList& QGCCorePlugin::toolBarIndicators(void)
449 450 451 452
{
    //-- Default list of indicators for all vehicles.
    if(_toolBarIndicatorList.size() == 0) {
        _toolBarIndicatorList = QVariantList({
453 454
                                                 QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSRTKIndicator.qml")),
                                             });
455 456 457
    }
    return _toolBarIndicatorList;
}
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502

QList<int> QGCCorePlugin::firstRunPromptStdIds(void)
{
    QList<int> rgStdIds = { unitsFirstRunPromptId, offlineVehicleFirstRunPromptId };
    return rgStdIds;
}

QList<int> QGCCorePlugin::firstRunPromptCustomIds(void)
{
    return QList<int>();
}

QVariantList QGCCorePlugin::firstRunPromptsToShow(void)
{
    QList<int> rgIdsToShow;

    rgIdsToShow.append(firstRunPromptStdIds());
    rgIdsToShow.append(firstRunPromptCustomIds());

    QList<int> rgAlreadyShownIds = AppSettings::firstRunPromptsIdsVariantToList(_toolbox->settingsManager()->appSettings()->firstRunPromptIdsShown()->rawValue());

    for (int idToRemove: rgAlreadyShownIds) {
        rgIdsToShow.removeOne(idToRemove);
    }

    QVariantList rgVarIdsToShow;
    for (int id: rgIdsToShow) {
        rgVarIdsToShow.append(id);
    }

    return rgVarIdsToShow;
}

QString QGCCorePlugin::firstRunPromptResource(int id)
{
    switch (id) {
    case unitsFirstRunPromptId:
        return "/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml";
    case offlineVehicleFirstRunPromptId:
        return "/FirstRunPromptDialogs/OfflineVehicleFirstRunPrompt.qml";
        break;
    }

    return QString();
}