sensoritem.cpp Example File

sensor_explorer/import/sensoritem.cpp
 /****************************************************************************
 **
 ** Copyright (C) 2017 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtSensors module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:BSD$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
 ** Software or, alternatively, in accordance with the terms contained in
 ** a written agreement between you and The Qt Company. For licensing terms
 ** and conditions see https://www.qt.io/terms-conditions. For further
 ** information use the contact form at https://www.qt.io/contact-us.
 **
 ** BSD License Usage
 ** Alternatively, you may use this file under the terms of the BSD license
 ** as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of The Qt Company Ltd nor the names of its
 **     contributors may be used to endorse or promote products derived
 **     from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 **
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/

 #include "sensoritem.h"
 #include <QtCore/QDebug>
 #include <QtSensors>

 /*
     \class QSensorItem
     \brief The QSensorItem type provides information about the metadata from a sensors installed on the system.
 */

 /*
     Construct a QSensorItem object with parent \a parent
 */
 QSensorItem::QSensorItem(QObject* parent)
     : QObject(parent)
     , _qsensor(0)
 {
 }

 /*
     Construct a QSensorItem object with QSensor \a sensor and parent \a parent
 */
 QSensorItem::QSensorItem(QSensor* sensor, QObject* parent)
     : QObject(parent)
     , _qsensor(sensor)
 {
 }

 /*
     Destructor of a QSensorItem
 */
 QSensorItem::~QSensorItem()
 {
 }

 /*
     \fn QSensorItem::startChanged()
     Notifies the client if the sensors has changed its start active status
 */

 /*
     \property QSensorItem::start
     This property starts or stops the sensor
 */
 bool QSensorItem::start()
 {
     return (_qsensor ? _qsensor->isActive() : false);
 }

 void QSensorItem::setStart(bool run)
 {
     if (_qsensor)
         _qsensor->setActive(run);
 }

 /*
     \property QSensorItem::id
     Returns the sensor id of the sensor item
 */
 QString QSensorItem::id()
 {
     return (_qsensor ? _qsensor->identifier() : "");
 }

 /*
     Set the new value \a val to the QPropertyInfo object \a property
 */
 void QSensorItem::changePropertyValue(QPropertyInfo* property, const QString& val)
 {
     if (_qsensor && _sensorProperties.contains(property)){
         if ( _qsensor->setProperty(property->name().toLatin1().constData(), QVariant(val)))
             updateSensorPropertyValues();
         else
             qWarning() << "new property value couldn't be set";
     }
 }

 /*
     Reading the metadata and activates the sensor.
 */
 void QSensorItem::select()
 {
     if (_sensorProperties.isEmpty()) {
         // Probe the reading using Qt's meta-object facilities
         //Read properties from reader
         QSensorReading *reading = _qsensor->reading();
         const QMetaObject *mo = reading->metaObject();
         int firstProperty = QSensorReading::staticMetaObject.propertyOffset();

         for (int i = firstProperty; i < mo->propertyCount(); ++i) {
             QString typeName = QLatin1String(mo->property(i).typeName());
             int crap = typeName.lastIndexOf("::");
             if (crap != -1)
                 typeName = typeName.mid(crap + 2);

             QPropertyInfo* pi = new QPropertyInfo(mo->property(i).name()
                                                   , i
                                                   , isWriteable(mo->property(i).name())
                                                   , typeName
                                                   , "-"
                                                   , this);
             _readerProperties.append(pi);
         }

         //Read properties from sensor
         const QMetaObject *mo1 = _qsensor->metaObject();
         firstProperty = QSensorReading::staticMetaObject.propertyOffset();

         for (int i = firstProperty; i < mo1->propertyCount(); ++i) {
             QString propertyname = mo1->property(i).name();
             if (ignoreProperty(propertyname))
                 continue;

             QString typeName = QLatin1String(mo1->property(i).typeName());
             int crap = typeName.lastIndexOf("::");
             if (crap != -1)
                 typeName = typeName.mid(crap + 2);

             QPropertyInfo* pi = new QPropertyInfo(propertyname
                                                   , i
                                                   , isWriteable(propertyname)
                                                   , typeName
                                                   , "-"
                                                   , this);
             _sensorProperties.append(pi);
         }
         updateSensorPropertyValues();
         connect(_qsensor, SIGNAL(readingChanged()), this, SLOT(sensorReadingChanged()));
     }
     connect(_qsensor, SIGNAL(activeChanged()), SIGNAL(startChanged()));
 }

 /*
     Unselect the sensor by stopping the sensor.
 */
 void QSensorItem::unSelect()
 {
     _qsensor->stop();
     disconnect(_qsensor, SIGNAL(activeChanged()), this , SIGNAL(startChanged()));
 }

 /*
     Updates the property values from QSensor
 */
 void QSensorItem::updateSensorPropertyValues()
 {
     if (_qsensor){
         const QMetaObject *mo = _qsensor->metaObject();
         for (int i = 0; i < _sensorProperties.count(); i++){
             QVariant val = mo->property(_sensorProperties[i]->index()).read(_qsensor);
             _sensorProperties[i]->setValue(convertValue(_sensorProperties[i]->typeName(), val));
         }
     }
 }

 /*
     \fn QSensorItem::propertiesChanged()
     Notifies the client if the list of the properties was changed
 */

 /*
     Updates the property values from the QSensorReader
 */
 void QSensorItem::sensorReadingChanged()
 {
     QSensorReading *reading = _qsensor->reading();
     const QMetaObject *mo = reading->metaObject();
     for (int i = 0; i < _readerProperties.count(); i++){
         QVariant val = mo->property(_readerProperties[i]->index()).read(reading);
         _readerProperties[i]->setValue(convertValue(_readerProperties[i]->typeName(), val));
     }
 }

 /*
     Returns true if the property with the name \a propertyname should be ignored
 */
 bool QSensorItem::ignoreProperty(const QString& propertyname)
 {
     if (propertyname == "reading" ||
         propertyname == "active" ||
         propertyname == "identifier" ||
         propertyname == "connectedToBackend" ||
         propertyname == "busy")
         return true;

     return false;
 }

 /*
     Returns true if the property with the name \a propertyname is writeable
 */
 bool QSensorItem::isWriteable(const QString& propertyname)
 {
     if (_qsensor){
         const QMetaObject *mo = _qsensor->metaObject();
         int propertyindex = mo->indexOfProperty(propertyname.toLocal8Bit().constData());
         if (propertyindex >= 0){
             QMetaProperty prop = mo->property(propertyindex);
             return prop.isWritable();
         }
         else {
             QSensorReading *reading = _qsensor->reading();
             const QMetaObject *moreader = reading->metaObject();
             propertyindex = moreader->indexOfProperty(propertyname.toLocal8Bit().constData());
             if (propertyindex >= 0){
                 QMetaProperty prop = mo->property(propertyindex);
                 return prop.isWritable();
             }
         }
     }

     return false;
 }

 /*
     Convert the variant \a val dependent on the type \a type and returns the converted value as a QString
 */
 QString QSensorItem::convertValue(const QString& type, const QVariant& val)
 {
     if (type == "LightLevel"){
         switch (val.toInt()) {
             case 1: return "Dark";
             case 2: return "Twilight";
             case 3: return "Light";
             case 4: return "Bright";
             case 5: return "Sunny";
             default: return "Undefined";
         }
     }
     else if (type == "Orientation"){
         switch (val.toInt()) {
             case 1: return "TopUp";
             case 2: return "TopDown";
             case 3: return "LeftUp";
             case 4: return "RightUp";
             case 5: return "FaceUp";
             case 6: return "FaceDown";
             default: return "Undefined";
         }
     }
     else if (type == "qrangelist"){
         qrangelist rangelist = val.value<qrangelist>();
         QStringList ranges;
         foreach (const qrange &r, rangelist) {
             if (r.first == r.second)
                 ranges << QString("%1 Hz").arg(r.first);
             else
                 ranges << QString("%1-%2 Hz").arg(r.first).arg(r.second);
         }
         if (ranges.count() > 0)
             return ranges.join(", ");
         return "-";
     }
     else if (type == "qoutputrangelist") {
         qoutputrangelist rangelist = val.value<qoutputrangelist>();
         QStringList ranges;
         foreach (const qoutputrange &r, rangelist) {
             ranges << QString("(%1, %2) += %3").arg(r.minimum).arg(r.maximum).arg(r.accuracy);
         }
         if (ranges.count() > 0)
             return ranges.join(", ");
         return "-";
     }

     return val.toString();
 }

 /*
     \property QSensorItem::properties
     Returns a list of all properties from the sensor
 */
 QQmlListProperty<QPropertyInfo> QSensorItem::properties()
 {
     _properties.clear();
     _properties.append(_sensorProperties);
     _properties.append(_readerProperties);
     return QQmlListProperty<QPropertyInfo> (this, _properties);
 }