qtmobility/src/sensors/qsensor.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 8 71781823f776
--- a/qtmobility/src/sensors/qsensor.cpp	Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/src/sensors/qsensor.cpp	Mon May 03 13:18:40 2010 +0300
@@ -63,6 +63,9 @@
 
 // A bit of a hack to call qRegisterMetaType when the library is loaded.
 static int qtimestamp_id = qRegisterMetaType<QtMobility::qtimestamp>("QtMobility::qtimestamp");
+static int qrange_id = qRegisterMetaType<QtMobility::qrange>("QtMobility::qrange");
+static int qrangelist_id = qRegisterMetaType<QtMobility::qrangelist>("QtMobility::qrangelist");
+static int qoutputrangelist_id = qRegisterMetaType<QtMobility::qoutputrangelist>("QtMobility::qoutputrangelist");
 
 // =====================================================================
 
@@ -87,12 +90,13 @@
 */
 
 /*!
-    Construct the sensor as a child of \a parent.
+    Construct the \a type sensor as a child of \a parent.
 */
-QSensor::QSensor(QObject *parent)
+QSensor::QSensor(const QByteArray &type, QObject *parent)
     : QObject(parent)
     , d(new QSensorPrivate)
 {
+    d->type = type;
 }
 
 /*!
@@ -112,15 +116,18 @@
 }
 
 /*!
-    \property QSensor::connected
+    \property QSensor::connectedToBackend
     \brief a value indicating if the sensor has connected to a backend.
 
     A sensor that has not been connected to a backend cannot do anything useful.
 
-    Call the connect() method to force the sensor to connect to a backend immediately.
+    Call the connectToBackend() method to force the sensor to connect to a backend
+    immediately. This is automatically called if you call start() so you only need
+    to do this if you need access to sensor properties (ie. to poll the sensor's
+    meta-data before you use it).
 */
 
-bool QSensor::isConnected() const
+bool QSensor::isConnectedToBackend() const
 {
     return (d->backend != 0);
 }
@@ -132,7 +139,7 @@
     Note that the identifier is filled out automatically
     when the sensor is connected to a backend. If you want
     to connect a specific backend, you should call
-    setIdentifier() before connect().
+    setIdentifier() before connectToBackend().
 */
 
 QByteArray QSensor::identifier() const
@@ -142,16 +149,16 @@
 
 void QSensor::setIdentifier(const QByteArray &identifier)
 {
-    Q_ASSERT(!d->backend);
+    if (d->backend) {
+        qWarning() << "ERROR: Cannot call QSensor::setIdentifier while connected to a backend!";
+        return;
+    }
     d->identifier = identifier;
 }
 
 /*!
     \property QSensor::type
     \brief the type of the sensor.
-
-    Note that setType() can only be used if you are using QSensor directly.
-    Sub-classes of QSensor call this automatically for you.
 */
 
 QByteArray QSensor::type() const
@@ -159,13 +166,6 @@
     return d->type;
 }
 
-void QSensor::setType(const QByteArray &type)
-{
-    Q_ASSERT(!d->backend);
-    Q_ASSERT(QLatin1String(metaObject()->className()) == QLatin1String("QSensor") || QLatin1String(metaObject()->className()) == QLatin1String(type));
-    d->type = type;
-}
-
 /*!
     Try to connect to a sensor backend.
 
@@ -173,28 +173,52 @@
 
     The type must be set before calling this method if you are using QSensor directly.
 
-    \sa isConnected()
+    \sa isConnectedToBackend()
 */
-bool QSensor::connect()
+bool QSensor::connectToBackend()
 {
     if (d->backend)
         return true;
 
-    if (d->type.isEmpty()) {
-        qWarning() << "QSensor::connect - Cannot call this method unless the type is set.";
-        return false;
-    }
-
+    int rate = d->dataRate;
     d->backend = QSensorManager::createBackend(this);
+    if (rate != 0)
+        setDataRate(rate);
     return (d->backend != 0);
 }
 
 /*!
-    \property QSensor::running
-    \brief controls the running state of the sensor.
+    \property QSensor::busy
+    \brief a value to indicate if the sensor is busy.
+
+    Some sensors may be on the system but unavailable for use.
+    This function will return true if the sensor is busy. You
+    will not be able to start() the sensor.
+
+    Note that this function does not return true if you
+    are using the sensor, only if another process is using
+    the sensor.
+
+    \sa busyChanged()
+*/
 
-    This is provided for QML, set running: true to cause the sensor
-    to start on.
+bool QSensor::isBusy() const
+{
+    return d->busy;
+}
+
+/*!
+    \fn QSensor::busyChanged()
+
+    This signal is emitted when the busy state changes. This can
+    be used to grab a sensor when it becomes available.
+*/
+
+/*!
+    \property QSensor::active
+    \brief a value to indicate if the sensor is active.
+
+    This is true if the sensor is active (returning values). This is false otherwise.
 */
 
 bool QSensor::isActive() const
@@ -202,158 +226,88 @@
     return d->active;
 }
 
-void QSensor::setActive(bool running)
+/*!
+    \property QSensor::availableDataRates
+    \brief the data rates that the sensor supports.
+
+    This is a list of the data rates that the sensor supports.
+    Entries in the list can represent discrete rates or a
+    continuous range of rates.
+    A discrete rate is noted by having both values the same.
+
+    See the sensor_explorer example for an example of how to interpret and use
+    this information.
+
+    \sa QSensor::dataRate
+*/
+
+qrangelist QSensor::availableDataRates() const
 {
-    if (d->complete) {
-        if (running)
-            start();
-        else
-            stop();
+    return d->availableDataRates;
+}
+
+/*!
+    \property QSensor::dataRate
+    \brief the data rate that the sensor should be run at.
+
+    The default value is determined by the backend.
+
+    This should be set before calling start() because the sensor may not
+    notice changes to this value while it is running.
+
+    \sa QSensor::availableDataRates
+*/
+
+int QSensor::dataRate() const
+{
+    return d->dataRate;
+}
+
+void QSensor::setDataRate(int rate)
+{
+    bool warn = true;
+    Q_FOREACH (const qrange &range, d->availableDataRates) {
+        if (rate >= range.first && rate <= range.second) {
+            warn = false;
+            d->dataRate = rate;
+            break;
+        }
+    }
+    if (warn) {
+        qWarning() << "setDataRate: rate" << rate << "is not supported by the sensor.";
     }
 }
 
 /*!
-    Returns true if the readingChanged() signal will be emitted.
-*/
-bool QSensor::isSignalEnabled() const
-{
-    return d->signalEnabled;
-}
-
-/*!
-    Call with \a enabled as false to turn off the readingChanged() signal.
-
-    You might want to do this for performance reasons. If you are polling
-    the sensor or using a filter in a performance-critical application
-    then the overhead of emitting the signal may be too high even if nothing
-    is connected to it.
-*/
-void QSensor::setSignalEnabled(bool enabled)
-{
-    d->signalEnabled = enabled;
-}
-
-/*!
-    \enum QSensor::UpdatePolicy
-
-    This enum is used to indicate to the sensor how often data will be collected.
-    Note that most sensors will only support one sensitivity. Setting an update
-    policy that the sensor does not support will result in undefined behaviour.
-    You can determine the policies the sensor supports with the
-    QSensor::supportedUpdatePolicies() method.
-
-    \value Undefined          The sensor has no specific update policy. Updates may
-                              arrive frequently or infrequently. Updates based on
-                              user interaction are likely to fit into this category.
-    \value OnChangeUpdates    Updates are delivered as they happen, usually based on
-                              user activity.
-    \value OccasionalUpdates  Updates are delivered occasionally, about one every
-                              5 seconds.
-    \value InfrequentUpdates  Updates are delivered infrequently, no more than once
-                              per second.
-    \value FrequentUpdates    Updates are delivered frequently, several per second.
-    \value TimedUpdates       Updates are delivered at a specific time interval.
-                              Note that not all sensors may be able to run with the
-                              exact timings requested and may operate slightly faster
-                              or slower.
-    \value PolledUpdates      Updates are retrieved when the currentReading()
-                              method is called.
-*/
-
-/*!
-    Change the update \a policy of the sensor. Note that not all
-    sensors support changing the update policy. If you set a
-    policy that the sensor does not support the behaviour is
-    undefined.
-
-    If you wish to use the TimedUpdates policy, please call
-    setUpdateInterval() with the desired interval.
-
-    \sa supportedUpdatePolicies()
-*/
-void QSensor::setUpdatePolicy(UpdatePolicy policy)
-{
-    if (policy == TimedUpdates)
-        return;
+    Start retrieving values from the sensor.
+    Returns true if the sensor was started, false otherwise.
 
-    d->updatePolicy = policy;
-    d->updateInterval = 0;
-}
-
-void QSensor::setUpdateInterval(int interval)
-{
-    d->updatePolicy = TimedUpdates;
-    d->updateInterval = interval;
-}
-
-/*!
-    \property QSensor::updatePolicy
-    \brief the update policy of the sensor.
-*/
-
-/*!
-    Returns the update policy the sensor is using.
-*/
-QSensor::UpdatePolicy QSensor::updatePolicy() const
-{
-    return d->updatePolicy;
-}
-
-/*!
-    \property QSensor::updateInterval
-    \brief the update interval of the sensor.
-
-    This value is only useful if the QSensor::updatePolicy property is set to TimedUpdates.
-*/
+    Note that the sensor may fail to start for several reasons.
 
-int QSensor::updateInterval() const
-{
-    return d->updateInterval;
-}
-
-/*!
-    \property QSensor::supportedUpdatePolicies
-    \brief the supported policies of the sensor.
-*/
-
-/*!
-    Returns the update policies that the sensor supports.
-
-    Note that this will return QSensor::Undefined until a sensor backend is connected.
-
-    \sa isConnected()
+    \sa QSensor::busy
 */
-QSensor::UpdatePolicies QSensor::supportedUpdatePolicies() const
-{
-    return d->supportedUpdatePolicies;
-}
-
-/*!
-    Poll the sensor.
-*/
-void QSensor::poll()
-{
-    if (!connect())
-        return;
-    if (d->updatePolicy == PolledUpdates)
-        d->backend->poll();
-}
-
-/*!
-    Start retrieving values from the sensor.
-*/
-void QSensor::start()
+bool QSensor::start()
 {
     if (d->active)
-        return;
-    if (!connect())
-        return;
+        return true;
+    if (!connectToBackend())
+        return false;
+    if (d->availableDataRates.count() == 0)
+        return false;
+    // Set these flags to their defaults
     d->active = true;
+    d->busy = false;
+    // Backend will update the flags appropriately
     d->backend->start();
+    return d->active;
 }
 
 /*!
     Stop retrieving values from the sensor.
+
+    This releases the sensor so that other processes can use it.
+
+    \sa QSensor::busy
 */
 void QSensor::stop()
 {
@@ -369,9 +323,9 @@
 
     The reading class provides access to sensor readings.
 
-    Note that this will return 0 until a sensor backend is connected.
+    Note that this will return 0 until a sensor backend is connected to a backend.
 
-    \sa isConnected()
+    \sa isConnectedToBackend()
 */
 
 QSensorReading *QSensor::reading() const
@@ -389,6 +343,10 @@
 */
 void QSensor::addFilter(QSensorFilter *filter)
 {
+    if (!filter) {
+        qWarning() << "addFilter: passed a null filter!";
+        return;
+    }
     d->filters << filter;
 }
 
@@ -399,6 +357,10 @@
 */
 void QSensor::removeFilter(QSensorFilter *filter)
 {
+    if (!filter) {
+        qWarning() << "removeFilter: passed a null filter!";
+        return;
+    }
     d->filters.removeOne(filter);
     filter->setSensor(0);
 }
@@ -414,6 +376,75 @@
     This signal is emitted when the reading has changed.
 */
 
+/*!
+    \property QSensor::outputRanges
+    \brief a list of output ranges the sensor supports.
+
+    A sensor may have more than one output range. Typically this is done
+    to give a greater measurement range at the cost of lowering accuracy.
+
+    \sa QSensor::outputRange
+*/
+
+qoutputrangelist QSensor::outputRanges() const
+{
+    return d->outputRanges;
+}
+
+/*!
+    \property QSensor::outputRange
+    \brief the output range in use by the sensor.
+
+    A sensor may have more than one output range. Typically this is done
+    to give a greater measurement range at the cost of lowering accuracy.
+
+    \sa QSensor::outputRanges
+*/
+
+int QSensor::outputRange() const
+{
+    return d->outputRange;
+}
+
+void QSensor::setOutputRange(int index)
+{
+    if (index < 0 || index >= d->outputRanges.count()) {
+        qWarning() << "ERROR: Output range" << index << "is not valid";
+        return;
+    }
+    d->outputRange = index;
+}
+
+/*!
+    \property QSensor::description
+    \brief a descriptive string for the sensor.
+*/
+
+QString QSensor::description() const
+{
+    return d->description;
+}
+
+/*!
+    \property QSensor::error
+    \brief the last error code set on the sensor.
+
+    Note that error codes are sensor-specific.
+*/
+
+int QSensor::error() const
+{
+    return d->error;
+}
+
+/*!
+    \fn QSensor::sensorError(int error)
+
+    This signal is emitted when an \a error code is set on the sensor.
+    Note that some errors will cause the sensor to stop working.
+    You should call isActive() to determine if the sensor is still running.
+*/
+
 // =====================================================================
 
 /*!
@@ -554,41 +585,31 @@
     Returns the value of the property at \a index.
 
     Note that this function is slower than calling the data function directly.
-    Consider the following statement that provides the best performance.
+
+    Here is an example of getting a property via the different mechanisms available.
+
+    Accessing directly provides the best performance but requires compile-time knowledge
+    of the data you are accessing.
 
     \code
     QAccelerometerReading *reading = ...;
     qreal x = reading->x();
     \endcode
 
-    The slowest way to access a property is via name. To do this you must call
-    QObject::property().
+    You can also access a property by name. To do this you must call QObject::property().
 
     \code
     qreal x = reading->property("x").value<qreal>();
     \endcode
 
-    This is about 20 times slower than simply calling x(). There are 3 costs here.
-
-    \list
-    \o The cost of the string comparison.
-    \o The cost of using the meta-object system.
-    \o The cost of converting to/from QVariant.
-    \endlist
-
-    By looking up the property via numeric index, the string comparison cost is
-    removed.
+    Finally, you can access values via numeric index.
 
     \code
     qreal x = reading->value(0).value<qreal>();
     \endcode
 
-    While faster than name-based lookup this is still about 20 times slower than
-    simply calling x().
-
-    Reading classes can opt to re-implement this function and bypass the
-    meta-object system. If this is done this function will be about 3 times slower
-    than simply calling x().
+    Note that value() can only access properties declared with Q_PROPERTY() in sub-classes
+    of QSensorReading.
 
     \sa valueCount(), QObject::property()
 */
@@ -607,12 +628,6 @@
     return property.read(this);
 }
 
-/*
-    \fn QSensorReading::value(int index) const
-
-    Returns the value of the property at \a index.
-*/
-
 /*!
     \fn QSensorReading::copyValuesFrom(QSensorReading *other)
     \internal