Fact.cc 11.7 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

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

#include "Fact.h"
Don Gagne's avatar
Don Gagne committed
28
#include "QGCMAVLink.h"
Don Gagne's avatar
Don Gagne committed
29 30 31

#include <QtQml>

Don Gagne's avatar
Don Gagne committed
32 33 34
Fact::Fact(QObject* parent)
    : QObject(parent)
    , _componentId(-1)
35
    , _rawValue(0)
Don Gagne's avatar
Don Gagne committed
36 37
    , _type(FactMetaData::valueTypeInt32)
    , _metaData(NULL)
Don Gagne's avatar
Don Gagne committed
38 39 40 41 42
{    
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
}

Don Gagne's avatar
Don Gagne committed
43 44 45 46
Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent)
    : QObject(parent)
    , _name(name)
    , _componentId(componentId)
47
    , _rawValue(0)
Don Gagne's avatar
Don Gagne committed
48 49
    , _type(type)
    , _metaData(NULL)
Don Gagne's avatar
Don Gagne committed
50
{
Don Gagne's avatar
Don Gagne committed
51 52 53
    FactMetaData* metaData = new FactMetaData(_type, this);
    setMetaData(metaData);
}
Don Gagne's avatar
Don Gagne committed
54

Don Gagne's avatar
Don Gagne committed
55 56 57 58 59 60 61 62 63 64
Fact::Fact(const Fact& other, QObject* parent)
    : QObject(parent)
{
    *this = other;
}

const Fact& Fact::operator=(const Fact& other)
{
    _name           = other._name;
    _componentId    = other._componentId;
65
    _rawValue          = other._rawValue;
Don Gagne's avatar
Don Gagne committed
66 67 68 69 70 71 72 73 74
    _type           = other._type;
    
    if (_metaData && other._metaData) {
        *_metaData = *other._metaData;
    } else {
        _metaData = NULL;
    }
    
    return *this;
Don Gagne's avatar
Don Gagne committed
75 76
}

Don Gagne's avatar
Don Gagne committed
77
void Fact::forceSetRawValue(const QVariant& value)
78 79 80 81 82 83
{
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
        if (_metaData->convertAndValidate(value, true /* convertOnly */, typedValue, errorString)) {
Don Gagne's avatar
Don Gagne committed
84 85 86
            _rawValue.setValue(typedValue);
            emit valueChanged(cookedValue());
            emit _containerRawValueChanged(rawValue());
87 88 89 90 91 92
        }
    } else {
        qWarning() << "Meta data pointer missing";
    }
}

93
void Fact::setRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
94
{
Don Gagne's avatar
Don Gagne committed
95 96 97 98 99
    if (_metaData) {
        QVariant    typedValue;
        QString     errorString;
        
        if (_metaData->convertAndValidate(value, true /* convertOnly */, typedValue, errorString)) {
100 101
            if (typedValue != _rawValue) {
                _rawValue.setValue(typedValue);
Don Gagne's avatar
Don Gagne committed
102 103
                emit valueChanged(cookedValue());
                emit _containerRawValueChanged(rawValue());
Don Gagne's avatar
Don Gagne committed
104 105 106 107
            }
        }
    } else {
        qWarning() << "Meta data pointer missing";
108
    }
Don Gagne's avatar
Don Gagne committed
109 110
}

Don Gagne's avatar
Don Gagne committed
111
void Fact::setCookedValue(const QVariant& value)
112 113 114 115 116 117 118 119 120 121 122 123 124
{
    if (_metaData) {
        setRawValue(_metaData->cookedTranslator()(value));
    } else {
        qWarning() << "Meta data pointer missing";
    }
}

void Fact::setEnumStringValue(const QString& value)
{
    if (_metaData) {
        int index = _metaData->enumStrings().indexOf(value);
        if (index != -1) {
Don Gagne's avatar
Don Gagne committed
125
            setCookedValue(_metaData->enumValues()[index]);
126 127 128 129 130 131 132 133 134
        }
    } else {
        qWarning() << "Meta data pointer missing";
    }
}

void Fact::setEnumIndex(int index)
{
    if (_metaData) {
Don Gagne's avatar
Don Gagne committed
135
        setCookedValue(_metaData->enumValues()[index]);
136 137 138 139 140
    } else {
        qWarning() << "Meta data pointer missing";
    }
}

Don Gagne's avatar
Don Gagne committed
141
void Fact::_containerSetRawValue(const QVariant& value)
Don Gagne's avatar
Don Gagne committed
142
{
143
    _rawValue = value;
Don Gagne's avatar
Don Gagne committed
144
    emit valueChanged(cookedValue());
145
    emit vehicleUpdated(_rawValue);
Don Gagne's avatar
Don Gagne committed
146
}
147 148 149 150 151 152

QString Fact::name(void) const
{
    return _name;
}

153 154 155 156 157
int Fact::componentId(void) const
{
    return _componentId;
}

Don Gagne's avatar
Don Gagne committed
158
QVariant Fact::cookedValue(void) const
159
{
160 161 162 163 164 165 166 167
    if (_metaData) {
        return _metaData->rawTranslator()(_rawValue);
    } else {
        qWarning() << "Meta data pointer missing";
        return _rawValue;
    }
}

168
QString Fact::enumStringValue(void)
169 170 171
{
    if (_metaData) {
        int enumIndex = this->enumIndex();
Don Gagne's avatar
Don Gagne committed
172
        if (enumIndex >= 0 && enumIndex < _metaData->enumStrings().count()) {
173 174 175 176 177 178 179 180 181
            return _metaData->enumStrings()[enumIndex];
        }
    } else {
        qWarning() << "Meta data pointer missing";
    }

    return QString();
}

182
int Fact::enumIndex(void)
183 184 185
{
    if (_metaData) {
        int index = 0;
186

187
        foreach (QVariant enumValue, _metaData->enumValues()) {
Don Gagne's avatar
Don Gagne committed
188
            if (enumValue == rawValue()) {
189 190 191 192
                return index;
            }
            index ++;
        }
193 194 195 196 197 198

        // Current value is not in list, add it manually
        _metaData->addEnumInfo(QString("Unknown: %1").arg(rawValue().toString()), rawValue());
        emit enumStringsChanged();
        emit enumValuesChanged();
        return index;
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    } else {
        qWarning() << "Meta data pointer missing";
    }

    return -1;
}

QStringList Fact::enumStrings(void) const
{
    if (_metaData) {
        return _metaData->enumStrings();
    } else {
        qWarning() << "Meta data pointer missing";
        return QStringList();
    }
}

QVariantList Fact::enumValues(void) const
{
    if (_metaData) {
        return _metaData->enumValues();
    } else {
        qWarning() << "Meta data pointer missing";
        return QVariantList();
    }
224 225
}

226
QString Fact::_variantToString(const QVariant& variant) const
227
{
228 229 230 231
    QString valueString;

    switch (type()) {
        case FactMetaData::valueTypeFloat:
232
            valueString = QString("%1").arg(variant.toFloat(), 0, 'f', decimalPlaces());
233 234
            break;
        case FactMetaData::valueTypeDouble:
235
            valueString = QString("%1").arg(variant.toDouble(), 0, 'f', decimalPlaces());
236 237
            break;
        default:
238
            valueString = variant.toString();
239 240 241 242
            break;
    }

    return valueString;
243 244
}

245 246
QString Fact::valueString(void) const
{
Don Gagne's avatar
Don Gagne committed
247
    return _variantToString(cookedValue());
248 249
}

250
QVariant Fact::defaultValue(void) const
251
{
Don Gagne's avatar
Don Gagne committed
252 253 254 255 256 257 258 259
    if (_metaData) {
        if (!_metaData->defaultValueAvailable()) {
            qDebug() << "Access to unavailable default value";
        }
        return _metaData->defaultValue();
    } else {
        qWarning() << "Meta data pointer missing";
        return QVariant(0);
260
    }
261 262
}

263 264 265 266 267
QString Fact::defaultValueString(void) const
{
    return _variantToString(defaultValue());
}

268
FactMetaData::ValueType_t Fact::type(void) const
269
{
270
    return _type;
271 272
}

273
QString Fact::shortDescription(void) const
274
{
Don Gagne's avatar
Don Gagne committed
275 276 277 278 279 280
    if (_metaData) {
        return _metaData->shortDescription();
    } else {
        qWarning() << "Meta data pointer missing";
        return QString();
    }
281 282
}

283
QString Fact::longDescription(void) const
284
{
Don Gagne's avatar
Don Gagne committed
285 286 287 288 289 290
    if (_metaData) {
        return _metaData->longDescription();
    } else {
        qWarning() << "Meta data pointer missing";
        return QString();
    }
291 292
}

293
QString Fact::units(void) const
294
{
Don Gagne's avatar
Don Gagne committed
295 296 297 298 299 300
    if (_metaData) {
        return _metaData->units();
    } else {
        qWarning() << "Meta data pointer missing";
        return QString();
    }
301 302
}

303
QVariant Fact::min(void) const
304
{
Don Gagne's avatar
Don Gagne committed
305 306 307 308 309 310
    if (_metaData) {
        return _metaData->min();
    } else {
        qWarning() << "Meta data pointer missing";
        return QVariant(0);
    }
311 312
}

313 314 315 316 317
QString Fact::minString(void) const
{
    return _variantToString(min());
}

318
QVariant Fact::max(void) const
319
{
Don Gagne's avatar
Don Gagne committed
320 321 322 323 324 325 326 327
    if (_metaData) {
        return _metaData->max();
    } else {
        qWarning() << "Meta data pointer missing";
        return QVariant(0);
    }
}

328 329 330 331 332
QString Fact::maxString(void) const
{
    return _variantToString(max());
}

333
bool Fact::minIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
334 335 336 337 338 339 340 341 342
{
    if (_metaData) {
        return _metaData->minIsDefaultForType();
    } else {
        qWarning() << "Meta data pointer missing";
        return false;
    }
}

343
bool Fact::maxIsDefaultForType(void) const
Don Gagne's avatar
Don Gagne committed
344 345 346 347 348 349 350
{
    if (_metaData) {
        return _metaData->maxIsDefaultForType();
    } else {
        qWarning() << "Meta data pointer missing";
        return false;
    }
351 352
}

353 354 355 356 357 358 359 360 361 362
int Fact::decimalPlaces(void) const
{
    if (_metaData) {
        return _metaData->decimalPlaces();
    } else {
        qWarning() << "Meta data pointer missing";
        return FactMetaData::defaultDecimalPlaces;
    }
}

363
QString Fact::group(void) const
364
{
Don Gagne's avatar
Don Gagne committed
365 366 367 368 369 370
    if (_metaData) {
        return _metaData->group();
    } else {
        qWarning() << "Meta data pointer missing";
        return QString();
    }
371 372
}

373 374
void Fact::setMetaData(FactMetaData* metaData)
{
Don Gagne's avatar
Don Gagne committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    static QStringList  apmFlightModeParamList;
    static QStringList  apmFlightModeEnumStrings;
    static QVariantList apmFlightModeEnumValues;

    static QStringList  apmChannelOptParamList;
    static QStringList  apmChannelOptEnumStrings;
    static QVariantList apmChannelOptEnumValues;

    // FIXME: Hack to stuff enums into APM parameters, wating on real APM metadata

    if (apmFlightModeEnumStrings.count() == 0) {
        apmFlightModeParamList << "FLTMODE1" << "FLTMODE2" << "FLTMODE3" << "FLTMODE4" << "FLTMODE5" << "FLTMODE6";
        apmFlightModeEnumStrings << "Stabilize" << "Acro" << "AltHold" << "Auto" << "Guided" << "Loiter" << "RTL" << "Circle"
                                 << "Land" << "Drift" << "Sport" << "Flip" << "AutoTune" << "PosHold" << "Brake";
        for (int i=0; i<apmFlightModeEnumStrings.count(); i++) {
            apmFlightModeEnumValues << QVariant(i);
        }

        apmChannelOptParamList << "CH7_OPT" << "CH8_OPT" << "CH9_OPT" << "CH10_OPT" << "CH11_OPT" << "CH12_OPT";
        apmChannelOptEnumStrings << "Do Nothing" << "Flip" << "Simple Mode" << "RTL" << "Save Trim" << "Save WP" << "Camera Trigger" << "RangeFinder"
                                 << "Fence" << "ResetToArmedYaw" << "Super Simple Mode" << "Acro Trainer" << "Auto" << "AutoTune" << "Land" << "EPM"
                                 << "Parachute Enable" << "Parachute Release" << "Parachute 3pos" << "Auto Mission Reset" << "AttCon Feed Forward"
                                 << "AttCon Accel Limits" << "Retract Mount" << "Relay On/Off" << "Landing Gear" << "Lost Copter Sound"
                                 << "Motor Emergency Stop" << "Motor Interlock" << "Brake";
        for (int i=0; i<apmChannelOptEnumStrings.count(); i++) {
            apmChannelOptEnumValues << QVariant(i);
        }
    }

    if (apmFlightModeParamList.contains(name())) {
        metaData->setEnumInfo(apmFlightModeEnumStrings, apmFlightModeEnumValues);
    } else if (apmChannelOptParamList.contains(name())) {
        metaData->setEnumInfo(apmChannelOptEnumStrings, apmChannelOptEnumValues);
    }

410
    _metaData = metaData;
Don Gagne's avatar
Don Gagne committed
411
    emit valueChanged(cookedValue());
412
}
413

414
bool Fact::valueEqualsDefault(void) const
415
{
Don Gagne's avatar
Don Gagne committed
416 417
    if (_metaData) {
        if (_metaData->defaultValueAvailable()) {
Don Gagne's avatar
Don Gagne committed
418
            return _metaData->defaultValue() == rawValue();
Don Gagne's avatar
Don Gagne committed
419 420 421
        } else {
            return false;
        }
422
    } else {
Don Gagne's avatar
Don Gagne committed
423
        qWarning() << "Meta data pointer missing";
424 425 426 427
        return false;
    }
}

428
bool Fact::defaultValueAvailable(void) const
429
{
Don Gagne's avatar
Don Gagne committed
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
    if (_metaData) {
        return _metaData->defaultValueAvailable();
    } else {
        qWarning() << "Meta data pointer missing";
        return false;
    }
}

QString Fact::validate(const QString& value, bool convertOnly)
{
    if (_metaData) {
        
        QVariant    typedValue;
        QString     errorString;
        
        _metaData->convertAndValidate(value, convertOnly, typedValue, errorString);
        
        return errorString;
    } else {
        qWarning() << "Meta data pointer missing";
        return QString("Internal error: Meta data pointer missing");
    }
}