GeoFenceController.cc 7.56 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/


/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "GeoFenceController.h"
#include "Vehicle.h"
#include "FirmwarePlugin.h"
#include "MAVLinkProtocol.h"
#include "QGCApplication.h"
19 20
#include "ParameterManager.h"
#include "JsonHelper.h"
21
#include "QGCQGeoCoordinate.h"
22
#include "AppSettings.h"
Don Gagne's avatar
Don Gagne committed
23 24

#ifndef __mobile__
25
#include "MainWindow.h"
26
#include "QGCQFileDialog.h"
Don Gagne's avatar
Don Gagne committed
27
#endif
28 29

#include <QJsonDocument>
30
#include <QJsonArray>
31 32 33

QGC_LOGGING_CATEGORY(GeoFenceControllerLog, "GeoFenceControllerLog")

34 35
const char* GeoFenceController::_jsonFileTypeValue =    "GeoFence";
const char* GeoFenceController::_jsonBreachReturnKey =  "breachReturn";
36

37 38 39
GeoFenceController::GeoFenceController(PlanMasterController* masterController, QObject* parent)
    : PlanElementController(masterController, parent)
    , _geoFenceManager(_managerVehicle->geoFenceManager())
40
    , _dirty(false)
41
    , _mapPolygon(this)
42
{
43 44
    connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::countChanged, this, &GeoFenceController::_updateContainsItems);
    connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged);
45 46

    managerVehicleChanged(_managerVehicle);
47 48 49 50 51 52 53 54 55 56 57 58
}

GeoFenceController::~GeoFenceController()
{

}

void GeoFenceController::start(bool editMode)
{
    qCDebug(GeoFenceControllerLog) << "start editMode" << editMode;

    PlanElementController::start(editMode);
59 60 61 62 63
    _init();
}

void GeoFenceController::_init(void)
{
64

65 66 67 68
}

void GeoFenceController::setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint)
{
69 70 71
    if (_breachReturnPoint != breachReturnPoint) {
        _breachReturnPoint = breachReturnPoint;
        setDirty(true);
72 73 74 75
        emit breachReturnPointChanged(breachReturnPoint);
    }
}

76
void GeoFenceController::_signalAll(void)
77
{
78 79
    emit breachReturnSupportedChanged(breachReturnSupported());
    emit breachReturnPointChanged(breachReturnPoint());
80
    emit circleEnabledChanged(circleEnabled());
81
    emit circleRadiusFactChanged(circleRadiusFact());
82
    emit polygonEnabledChanged(polygonEnabled());
83
    emit polygonSupportedChanged(polygonSupported());
84
    emit dirtyChanged(dirty());
85 86
}

87
void GeoFenceController::managerVehicleChanged(Vehicle* managerVehicle)
88
{
89 90 91 92 93
    if (_managerVehicle) {
        _geoFenceManager->disconnect(this);
        _managerVehicle = NULL;
        _geoFenceManager = NULL;
    }
94

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    _managerVehicle = managerVehicle;
    if (!_managerVehicle) {
        qWarning() << "GeoFenceController::managerVehicleChanged managerVehicle=NULL";
        return;
    }

    _geoFenceManager = _managerVehicle->geoFenceManager();
    connect(_geoFenceManager, &GeoFenceManager::breachReturnSupportedChanged,   this, &GeoFenceController::breachReturnSupportedChanged);
    connect(_geoFenceManager, &GeoFenceManager::circleEnabledChanged,           this, &GeoFenceController::circleEnabledChanged);
    connect(_geoFenceManager, &GeoFenceManager::circleRadiusFactChanged,        this, &GeoFenceController::circleRadiusFactChanged);
    connect(_geoFenceManager, &GeoFenceManager::polygonEnabledChanged,          this, &GeoFenceController::polygonEnabledChanged);
    connect(_geoFenceManager, &GeoFenceManager::polygonSupportedChanged,        this, &GeoFenceController::polygonSupportedChanged);
    connect(_geoFenceManager, &GeoFenceManager::loadComplete,                   this, &GeoFenceController::_loadComplete);
    connect(_geoFenceManager, &GeoFenceManager::inProgressChanged,              this, &GeoFenceController::syncInProgressChanged);

Don Gagne's avatar
Don Gagne committed
110
    _signalAll();
111
}
Don Gagne's avatar
Don Gagne committed
112

113
bool GeoFenceController::load(const QJsonObject& json, QString& errorString)
114
{
115 116
    QString errorStr;
    QString errorMessage = tr("GeoFence: %1");
117

118 119 120
    if (json.contains(_jsonBreachReturnKey) &&
            !JsonHelper::loadGeoCoordinate(json[_jsonBreachReturnKey], false /* altitudeRequired */, _breachReturnPoint, errorStr)) {
        errorString = errorMessage.arg(errorStr);
121 122 123
        return false;
    }

124 125
    if (!_mapPolygon.loadFromJson(json, true, errorStr)) {
        errorString = errorMessage.arg(errorStr);
126
        return false;
127
    }
128
    _mapPolygon.setDirty(false);
129
    setDirty(false);
130

131
    _signalAll();
132 133

    return true;
134 135
}

136
void  GeoFenceController::save(QJsonObject& json)
137
{
138
    json[JsonHelper::jsonVersionKey] = 1;
139

140
    if (_breachReturnPoint.isValid()) {
141 142
        QJsonValue jsonBreachReturn;
        JsonHelper::saveGeoCoordinate(_breachReturnPoint, false /* writeAltitude */, jsonBreachReturn);
143
        json[_jsonBreachReturnKey] = jsonBreachReturn;
144 145
    }

146
    _mapPolygon.saveToJson(json);
147 148
}

149 150
void GeoFenceController::removeAll(void)
{
151
    setBreachReturnPoint(QGeoCoordinate());
152
    _mapPolygon.clear();
153 154 155 156
}

void GeoFenceController::loadFromVehicle(void)
{
157 158
    if (!syncInProgress()) {
        _geoFenceManager->loadFromVehicle();
159
    } else {
160
        qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call while syncInProgress";
161 162 163 164 165
    }
}

void GeoFenceController::sendToVehicle(void)
{
166 167 168
    _geoFenceManager->sendToVehicle(_breachReturnPoint, _mapPolygon.pathModel());
    _mapPolygon.setDirty(false);
    setDirty(false);
169 170 171 172
}

bool GeoFenceController::syncInProgress(void) const
{
173
    return _geoFenceManager->inProgress();
174 175 176 177
}

bool GeoFenceController::dirty(void) const
{
178
    return _dirty;
179 180 181 182 183 184 185 186
}


void GeoFenceController::setDirty(bool dirty)
{
    if (dirty != _dirty) {
        _dirty = dirty;
        if (!dirty) {
187
            _mapPolygon.setDirty(dirty);
188 189 190 191 192 193 194 195 196 197 198
        }
        emit dirtyChanged(dirty);
    }
}

void GeoFenceController::_polygonDirtyChanged(bool dirty)
{
    if (dirty) {
        setDirty(true);
    }
}
199

200 201
bool GeoFenceController::breachReturnSupported(void) const
{
202
    return _geoFenceManager->breachReturnSupported();
203 204
}

205
bool GeoFenceController::circleEnabled(void) const
206
{
207
    return _geoFenceManager->circleEnabled();
208 209
}

210 211
Fact* GeoFenceController::circleRadiusFact(void) const
{
212
    return _geoFenceManager->circleRadiusFact();
213 214 215 216
}

bool GeoFenceController::polygonSupported(void) const
{
217
    return _geoFenceManager->polygonSupported();
218 219
}

220
bool GeoFenceController::polygonEnabled(void) const
221
{
222
    return _geoFenceManager->polygonEnabled();
223 224
}

225
QVariantList GeoFenceController::params(void) const
226
{
227
    return _geoFenceManager->params();
228 229 230 231
}

QStringList GeoFenceController::paramLabels(void) const
{
232
    return _geoFenceManager->paramLabels();
233 234 235 236 237 238 239
}

void GeoFenceController::_setDirty(void)
{
    setDirty(true);
}

240
void GeoFenceController::_setPolygonFromManager(const QList<QGeoCoordinate>& polygon)
241
{
242 243 244 245 246
    _mapPolygon.clear();
    for (int i=0; i<polygon.count(); i++) {
        _mapPolygon.appendVertex(polygon[i]);
    }
    _mapPolygon.setDirty(false);
247 248 249 250 251 252
}

void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
{
    _breachReturnPoint = breachReturnPoint;
    emit breachReturnPointChanged(_breachReturnPoint);
253 254
}

255 256 257 258 259
void GeoFenceController::_loadComplete(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon)
{
    _setReturnPointFromManager(breachReturn);
    _setPolygonFromManager(polygon);
    setDirty(false);
Don Gagne's avatar
Don Gagne committed
260
    emit loadComplete();
261
}
262

263 264 265 266 267 268 269 270 271 272 273 274
bool GeoFenceController::containsItems(void) const
{
    return _mapPolygon.count() > 2;
}

void GeoFenceController::_updateContainsItems(void)
{
    emit containsItemsChanged(containsItems());
}

void GeoFenceController::removeAllFromVehicle(void)
{
275
    _geoFenceManager->removeAll();
276
}