QGCCorePlugin.cc 17.4 KB
Newer Older
1 2
/****************************************************************************
 *
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 19 20
#include "VideoManager.h"
#if defined(QGC_GST_STREAMING)
#include "GStreamer.h"
21
#include "VideoReceiver.h"
22
#endif
23 24 25 26
#include "QGCLoggingCategory.h"
#include "QGCCameraManager.h"
#include "HorizontalFactValueGrid.h"
#include "InstrumentValueData.h"
27

28 29 30 31 32
#include <QtQml>
#include <QQmlEngine>

/// @file
///     @brief Core Plugin Interface for QGroundControl - Default Implementation
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 154 155 156 157
#if defined(QGC_GST_MICROHARD_ENABLED)
        _p->pMicrohard = new QmlComponentInfo(tr("Microhard"),
                                              QUrl::fromUserInput("qrc:/qml/MicrohardSettings.qml"),
                                              QUrl::fromUserInput(""));
        _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 183 184
        _p->pQmlTest = new QmlComponentInfo(tr("Palette Test"),
                                            QUrl::fromUserInput("qrc:/qml/QmlTest.qml"));
        _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
QVariantList& QGCCorePlugin::analyzePages()
191
{
192 193 194 195
    if (!_p->analyzeList.count()) {
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("Log Download"),     QUrl::fromUserInput("qrc:/qml/LogDownloadPage.qml"),        QUrl::fromUserInput("qrc:/qmlimages/LogDownloadIcon"))));
#if !defined(__mobile__)
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("GeoTag Images"),    QUrl::fromUserInput("qrc:/qml/GeoTagPage.qml"),             QUrl::fromUserInput("qrc:/qmlimages/GeoTagIcon"))));
Gus Grubba's avatar
Gus Grubba committed
196
#endif
197 198 199
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("MAVLink Console"),  QUrl::fromUserInput("qrc:/qml/MavlinkConsolePage.qml"),     QUrl::fromUserInput("qrc:/qmlimages/MavlinkConsoleIcon"))));
#if defined(QGC_ENABLE_MAVLINK_INSPECTOR)
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("MAVLink Inspector"),QUrl::fromUserInput("qrc:/qml/MAVLinkInspectorPage.qml"),   QUrl::fromUserInput("qrc:/qmlimages/MAVLinkInspector"))));
Gus Grubba's avatar
Gus Grubba committed
200
#endif
201
        _p->analyzeList.append(QVariant::fromValue(new QmlComponentInfo(tr("Vibration"),        QUrl::fromUserInput("qrc:/qml/VibrationPage.qml"),          QUrl::fromUserInput("qrc:/qmlimages/VibrationPageIcon"))));
202
    }
203
    return _p->analyzeList;
204 205
}

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 230 231 232 233 234 235 236 237
    if (settingsGroup == AppSettings::settingsGroup) {
#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 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
    HorizontalFactValueGrid factValueGrid(defaultSettingsGroup);

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

    factValueGrid.setFontSize(FactValueGrid::LargeFontSize);

    factValueGrid.appendColumn();
    factValueGrid.appendColumn();
    factValueGrid.appendColumn();
    if (includeFWValues) {
        factValueGrid.appendColumn();
    }
    factValueGrid.appendRow();

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

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

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

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

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

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


    if (includeFWValues) {
        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++);
        value->setFact("Vehicle", "ThrottlePct");
        value->setText("Thr");
        value->setShowUnits(true);
    }

    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++);
    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 433
void QGCCorePlugin::releaseVideoSink(void* sink)
{
#if defined(QGC_GST_STREAMING)
    GStreamer::releaseVideoSink(sink);
#else
    Q_UNUSED(sink)
#endif
}

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 453 454 455 456 457 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
    //-- Default list of indicators for all vehicles.
    if(_toolBarIndicatorList.size() == 0) {
        _toolBarIndicatorList = QVariantList({
                                                 QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSRTKIndicator.qml")),
                                             });
    }
    return _toolBarIndicatorList;
}

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();
502
}