diff options
-rw-r--r-- | src/imports/sensors/plugins.qmltypes | 15 | ||||
-rw-r--r-- | src/imports/sensors/qmlsensor.cpp | 53 | ||||
-rw-r--r-- | src/imports/sensors/qmlsensor.h | 23 | ||||
-rw-r--r-- | src/plugins/sensors/blackberry/bbcompass.cpp | 15 | ||||
-rw-r--r-- | src/plugins/sensors/blackberry/bbsensorbackend.cpp | 35 | ||||
-rw-r--r-- | src/plugins/sensors/blackberry/bbsensorbackend.h | 2 | ||||
-rw-r--r-- | src/sensors/qsensor.cpp | 175 | ||||
-rw-r--r-- | src/sensors/qsensor.h | 24 | ||||
-rw-r--r-- | src/sensors/qsensor_p.h | 7 |
9 files changed, 338 insertions, 11 deletions
diff --git a/src/imports/sensors/plugins.qmltypes b/src/imports/sensors/plugins.qmltypes index fe9c961d..94db26d0 100644 --- a/src/imports/sensors/plugins.qmltypes +++ b/src/imports/sensors/plugins.qmltypes @@ -172,10 +172,25 @@ Module { Property { name: "error"; type: "int"; isReadonly: true } Property { name: "alwaysOn"; type: "bool" } Property { name: "skipDuplicates"; revision: 1; type: "bool" } + Property { name: "axesOrientationMode"; revision: 1; type: "AxesOrientationMode" } + Property { name: "currentOrientation"; revision: 1; type: "int"; isReadonly: true } + Property { name: "userOrientation"; revision: 1; type: "int" } Signal { name: "skipDuplicatesChanged" Parameter { name: "skipDuplicates"; type: "bool" } } + Signal { + name: "axesOrientationModeChanged" + Parameter { name: "axesOrientationMode"; type: "AxesOrientationMode" } + } + Signal { + name: "currentOrientationChanged" + Parameter { name: "currentOrientation"; type: "int" } + } + Signal { + name: "userOrientationChanged" + Parameter { name: "userOrientation"; type: "int" } + } Method { name: "start"; type: "bool" } Method { name: "stop" } } diff --git a/src/imports/sensors/qmlsensor.cpp b/src/imports/sensors/qmlsensor.cpp index 40a0ebfe..727526ae 100644 --- a/src/imports/sensors/qmlsensor.cpp +++ b/src/imports/sensors/qmlsensor.cpp @@ -307,6 +307,55 @@ QmlSensorReading *QmlSensor::reading() const } /*! + \qmlproperty Sensor::AxesOrientationMode Sensor::axesOrientationMode + \since QtSensors 5.1 + This property holds the mode that affects how the screen orientation changes reading values. + + Please see QSensor::axesOrientationMode for information about this property. +*/ + +QmlSensor::AxesOrientationMode QmlSensor::axesOrientationMode() const +{ + return static_cast<QmlSensor::AxesOrientationMode>(sensor()->axesOrientationMode()); +} + +void QmlSensor::setAxesOrientationMode(QmlSensor::AxesOrientationMode axesOrientationMode) +{ + sensor()->setAxesOrientationMode(static_cast<QSensor::AxesOrientationMode>(axesOrientationMode)); +} + +/*! + \qmlproperty int Sensor::currentOrientation + \since QtSensors 5.1 + This property holds the current orientation that is used for rotating the reading values. + + Please see QSensor::currentOrientation for information about this property. +*/ + +int QmlSensor::currentOrientation() const +{ + return sensor()->currentOrientation(); +} + +/*! + \qmlproperty int Sensor::userOrientation + \since QtSensors 5.1 + This property holds the angle used for rotating the reading values in the UserOrientation mode. + + Please see QSensor::userOrientation for information about this property. +*/ + +int QmlSensor::userOrientation() const +{ + return sensor()->userOrientation(); +} + +void QmlSensor::setUserOrientation(int userOrientation) +{ + sensor()->setUserOrientation(userOrientation); +} + +/*! \qmlmethod bool Sensor::start() Start retrieving values from the sensor. Returns true if the sensor was started, false otherwise. @@ -343,6 +392,10 @@ void QmlSensor::componentComplete() connect(sensor(), SIGNAL(activeChanged()), this, SIGNAL(activeChanged())); connect(sensor(), SIGNAL(alwaysOnChanged()), this, SIGNAL(alwaysOnChanged())); connect(sensor(), SIGNAL(skipDuplicatesChanged(bool)), this, SIGNAL(skipDuplicatesChanged(bool))); + connect(sensor(), SIGNAL(axesOrientationModeChanged(AxesOrientationMode)), + this, SIGNAL(axesOrientationModeChanged(AxesOrientationMode))); + connect(sensor(), SIGNAL(userOrientationChanged(int)), this, SIGNAL(userOrientationChanged(int))); + connect(sensor(), SIGNAL(currentOrientationChanged(int)), this, SIGNAL(currentOrientationChanged(int))); // We need to set this on the sensor object now sensor()->setIdentifier(m_identifier.toLocal8Bit()); diff --git a/src/imports/sensors/qmlsensor.h b/src/imports/sensors/qmlsensor.h index e287f194..9b8f7b75 100644 --- a/src/imports/sensors/qmlsensor.h +++ b/src/imports/sensors/qmlsensor.h @@ -57,6 +57,7 @@ class QmlSensorReading; class QmlSensor : public QObject, public QQmlParserStatus { Q_OBJECT + Q_ENUMS(AxesOrientationMode) Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString identifier READ identifier WRITE setIdentifier NOTIFY identifierChanged) Q_PROPERTY(QString type READ type NOTIFY typeChanged) @@ -72,7 +73,18 @@ class QmlSensor : public QObject, public QQmlParserStatus Q_PROPERTY(int error READ error NOTIFY errorChanged) Q_PROPERTY(bool alwaysOn READ isAlwaysOn WRITE setAlwaysOn NOTIFY alwaysOnChanged) Q_PROPERTY(bool skipDuplicates READ skipDuplicates WRITE setSkipDuplicates NOTIFY skipDuplicatesChanged REVISION 1) + Q_PROPERTY(AxesOrientationMode axesOrientationMode READ axesOrientationMode WRITE setAxesOrientationMode NOTIFY axesOrientationModeChanged REVISION 1) + Q_PROPERTY(int currentOrientation READ currentOrientation NOTIFY currentOrientationChanged REVISION 1) + Q_PROPERTY(int userOrientation READ userOrientation WRITE setUserOrientation NOTIFY userOrientationChanged REVISION 1) + public: + // Keep in sync with QSensor::AxesOrientationMode + enum AxesOrientationMode { + FixedOrientation, + AutomaticOrientation, + UserOrientation + }; + explicit QmlSensor(QObject *parent = 0); ~QmlSensor(); @@ -107,6 +119,14 @@ public: QmlSensorReading *reading() const; + AxesOrientationMode axesOrientationMode() const; + void setAxesOrientationMode(AxesOrientationMode axesOrientationMode); + + int currentOrientation() const; + + int userOrientation() const; + void setUserOrientation(int userOrientation); + public Q_SLOTS: bool start(); void stop(); @@ -125,6 +145,9 @@ Q_SIGNALS: void errorChanged(); void alwaysOnChanged(); void skipDuplicatesChanged(bool skipDuplicates); + void axesOrientationModeChanged(AxesOrientationMode axesOrientationMode); + void currentOrientationChanged(int currentOrientation); + void userOrientationChanged(int userOrientation); protected: virtual QSensor *sensor() const = 0; diff --git a/src/plugins/sensors/blackberry/bbcompass.cpp b/src/plugins/sensors/blackberry/bbcompass.cpp index 6e33d1a3..df8cc2e1 100644 --- a/src/plugins/sensors/blackberry/bbcompass.cpp +++ b/src/plugins/sensors/blackberry/bbcompass.cpp @@ -55,19 +55,28 @@ BbCompass::BbCompass(QSensor *sensor) bool BbCompass::updateReadingFromEvent(const sensor_event_t &event, QCompassReading *reading) { + float azimuth; #ifdef HAVE_COMPASS_SENSOR - reading->setAzimuth(event.compass_s.azimuth); + azimuth = event.compass_s.azimuth; #else float xRad, yRad, zRad; matrixToEulerZXY(event.rotation_matrix, xRad, yRad, zRad); - float azimuth = radiansToDegrees(zRad); + azimuth = radiansToDegrees(zRad); if (azimuth < 0) azimuth = -azimuth; else azimuth = 360.0f - azimuth; - reading->setAzimuth(azimuth); #endif + if (isAutoAxisRemappingEnabled()) { + azimuth += orientationForRemapping(); + if (azimuth >= 360.0f) + azimuth -= 360.0f; + } + + reading->setAzimuth(azimuth); + + switch (event.accuracy) { case SENSOR_ACCURACY_UNRELIABLE: reading->setCalibrationLevel(0.0f); diff --git a/src/plugins/sensors/blackberry/bbsensorbackend.cpp b/src/plugins/sensors/blackberry/bbsensorbackend.cpp index 9850d4dd..de6661e2 100644 --- a/src/plugins/sensors/blackberry/bbsensorbackend.cpp +++ b/src/plugins/sensors/blackberry/bbsensorbackend.cpp @@ -86,6 +86,7 @@ BbSensorBackendBase::BbSensorBackendBase(const QString &devicePath, sensor_type_ m_mappingMatrix[0] = m_mappingMatrix[3] = 1; m_mappingMatrix[1] = m_mappingMatrix[2] = 0; connect(sensor, SIGNAL(alwaysOnChanged()), this, SLOT(applyAlwaysOnProperty())); + connect(sensor, SIGNAL(userOrientationChanged(int)), this, SLOT(updateOrientation())); // Set some sensible default values sensor->setProperty("efficientBufferSize", defaultBufferSize); @@ -183,12 +184,13 @@ qreal BbSensorBackendBase::convertValue(float bbValue) bool BbSensorBackendBase::isAutoAxisRemappingEnabled() const { - return sensor()->property("automaticAxisRemapping").toBool(); + return sensor()->isFeatureSupported(QSensor::AxesOrientation) && + sensor()->axesOrientationMode() != QSensor::FixedOrientation; } void BbSensorBackendBase::remapMatrix(const float inputMatrix[], float outputMatrix[]) { - if (!isAutoAxisRemappingEnabled() || m_guiHelper->currentOrientation() == 0) { + if (!isAutoAxisRemappingEnabled() || orientationForRemapping() == 0) { memcpy(outputMatrix, inputMatrix, sizeof(float) * 9); return; } @@ -199,10 +201,10 @@ void BbSensorBackendBase::remapMatrix(const float inputMatrix[], float outputMat void BbSensorBackendBase::remapAxes(float *x, float *y, float *z) { Q_ASSERT(x && y && z); - if (!isAutoAxisRemappingEnabled() || m_guiHelper->currentOrientation() == 0) + if (!isAutoAxisRemappingEnabled() || orientationForRemapping() == 0) return; - const int angle = m_guiHelper->currentOrientation(); + const int angle = orientationForRemapping(); const float oldX = *x; const float oldY = *y; @@ -306,6 +308,11 @@ void BbSensorBackendBase::stop() bool BbSensorBackendBase::isFeatureSupported(QSensor::Feature feature) const { switch (feature) { + case QSensor::AxesOrientation: + return (sensorType() == SENSOR_TYPE_ACCELEROMETER || sensorType() == SENSOR_TYPE_MAGNETOMETER || + sensorType() == SENSOR_TYPE_GYROSCOPE || sensorType() == SENSOR_TYPE_GRAVITY || + sensorType() == SENSOR_TYPE_LINEAR_ACCEL || sensorType() == SENSOR_TYPE_ROTATION_VECTOR || + sensorType() == SENSOR_TYPE_ROTATION_MATRIX || sensorType() == SENSOR_TYPE_AZIMUTH_PITCH_ROLL); case QSensor::AlwaysOn: case QSensor::Buffering: case QSensor::AccelerationMode: @@ -387,12 +394,26 @@ void BbSensorBackendBase::updatePauseState() void BbSensorBackendBase::updateOrientation() { - // ### I can't really test this, the rotation matrix has too many glitches and drifts over time, - // making any measurement quite hard - const int rotationAngle = guiHelper()->currentOrientation(); + const int rotationAngle = orientationForRemapping(); m_mappingMatrix[0] = cos(rotationAngle*M_PI/180); m_mappingMatrix[1] = sin(rotationAngle*M_PI/180); m_mappingMatrix[2] = -sin(rotationAngle*M_PI/180); m_mappingMatrix[3] = cos(rotationAngle*M_PI/180); + + if (sensor()->isFeatureSupported(QSensor::AxesOrientation)) + sensor()->setCurrentOrientation(rotationAngle); +} + +int BbSensorBackendBase::orientationForRemapping() const +{ + if (!sensor()->isFeatureSupported(QSensor::AxesOrientation)) + return 0; + + switch (sensor()->axesOrientationMode()) { + default: + case QSensor::FixedOrientation: return 0; + case QSensor::AutomaticOrientation: return guiHelper()->currentOrientation(); + case QSensor::UserOrientation: return sensor()->userOrientation(); + } } diff --git a/src/plugins/sensors/blackberry/bbsensorbackend.h b/src/plugins/sensors/blackberry/bbsensorbackend.h index cd9a0e22..48a72163 100644 --- a/src/plugins/sensors/blackberry/bbsensorbackend.h +++ b/src/plugins/sensors/blackberry/bbsensorbackend.h @@ -75,8 +75,8 @@ public: protected: BbGuiHelper *guiHelper() const; QFile& deviceFile(); - sensor_type_e sensorType() const; + int orientationForRemapping() const; void setDevice(const QString &deviceFile, sensor_type_e sensorType); diff --git a/src/sensors/qsensor.cpp b/src/sensors/qsensor.cpp index f93ef883..125d5924 100644 --- a/src/sensors/qsensor.cpp +++ b/src/sensors/qsensor.cpp @@ -176,6 +176,40 @@ void QSensorPrivate::init(const QByteArray &sensorType) The sensor data is delivered via QSensorReading and its sub-classes. + \section1 Orientation + + Some sensors react to screen orientation changes, such as QAccelerometer, QMagnetometer and + QRotationSensor. These are so called \e orientable sensors. For orientable sensors, + QSensor supports changing the reporting of the reading values based on the orientation of the + screen. + + For orientable sensors, the axesOrientationMode property controls how the orientation affects + the reading values. + + In the default mode, QSensor::FixedOrientation, the reading values remain + unaffected by the orientation. In the QSensor::AutomaticOrientation mode, the reading + values are automatically rotated by taking the current screen orientation into account. And + finally, in the QSensor::UserOrientation mode, the reading values are rotated + according to a user-specified orientation. + + The functionality of this is only available if it is supported by the backend and if the sensor + is orientable, which can be checked by calling QSensor::isFeatureSupported() + with the QSensor::AxesOrientation flag. + + The orientation values here are always of the screen orientation, not the device orientation. + The screen orientation is the orientation of the GUI. For example when rotating a device by 90 + degrees counter-clockwise, the screen orientation compensates for that by rotating 90 degrees + clockwise, to the effect that the GUI is still facing upright after the device has been rotated. + Note that applications can lock the screen orientation, for example to force portrait or landscape + mode. For locked orientations, orientable sensors will not react with reading changes if the device + orientation is changed, as orientable sensors react to screen orientation changes only. This makes + sense, as the purpose of orientable sensors is to keep the sensor orientation in sync with the screen + orientation. + + The orientation values range from 0 to 270 degrees. The orientation is applied in clockwise direction, + e.g. an orientation value of 90 degrees means that the screen has been rotated 90 degress to the right + from its origin position, to compensate a device rotation of 90 degrees to the left. + \sa QSensorReading */ @@ -208,6 +242,11 @@ void QSensorPrivate::init(const QByteArray &sensorType) \value AccelerationMode The backend supports switching the acceleration mode of the acceleromter with the QAccelerometer::accelerationMode property. + The features of all orientable sensors are: + + \value AxesOrientation The backend supports changing the axes orientation from the default of + QSensor::FixedOrientation to something else. + \omitvalue Reserved \sa QSensor::isFeatureSupported() @@ -816,6 +855,142 @@ int QSensor::error() const } /*! + \enum QSensor::AxesOrientationMode + \since 5.1 + + Describes how reading values are affected by the screen orientation. + + \value FixedOrientation No automatic rotation is applied to the reading values. + + \value AutomaticOrientation The reading values are automatically rotated based on the screen + orientation. + + \value UserOrientation The reading values are rotated based on the angle of the userOrientation property. + + \sa QSensor::axesOrientationMode +*/ + +/*! + \property QSensor::axesOrientationMode + \since 5.1 + \brief The mode that affects how the screen orientation changes reading values. + + When set to FixedOrientation, which is the default mode, no automatic rotation is applied to + the reading. This is the only mode available for backends that do not support the + QSensor::AxesOrientation feature. + + When set to AutomaticOrientation, the reading values are automatically rotated when the + screen orientation changes. In effect, the screen orientation is canceled out. + + As an example, assume the device is rotated by 180 degrees and therefore the screen orientation + also is rotated by 180 degrees from the native orientation. Without automatic axes orientation, + the reading values would now be changed: Both the X and the Y values would be negated, forcing + an application developer to manually cancel out the negation in application code. Automatic + axes orientation does this automatically, in this mode the X and Y values would be the same as + with the default screen orientation. + + This automatic rotation of the axes is handy is some usecases, for example in a bubble level + application that measures how level a surface is by looking at the X axis value of an + accelerometer. When the device and screen orientation change by 90 degrees, an application + developer does not need to change anything, he can continue using the X axis value even though + the device is rotated. Without automatic axes orientation, the application developer would need + to look at the Y values instead, thereby adding code to the application that reads from a + different axis depending on the screen orientation. + + The UserOrientation mode is quite similar to AutomaticOrientation, only that the screen orientation + is manually controlled instead of automatically determined. The angle of the userOrientation + property is then used for rotating the reading values. + + Since the rotation of the reading values is based on the screen orientation, Z values will never + change, as the Z axis is perpendicular to the screen. + As screen orientation changes in 90 degree steps, rotating the reading values is also done in + steps of 90 degrees. + + This property is only used for orientable sensors. +*/ + +QSensor::AxesOrientationMode QSensor::axesOrientationMode() const +{ + Q_D(const QSensor); + return d->axesOrientationMode; +} + +void QSensor::setAxesOrientationMode(QSensor::AxesOrientationMode axesOrientationMode) +{ + Q_D(QSensor); + if (d->axesOrientationMode != axesOrientationMode) { + d->axesOrientationMode = axesOrientationMode; + emit axesOrientationModeChanged(axesOrientationMode); + } +} + +/*! + \property QSensor::currentOrientation + \since 5.1 + \brief The current orientation that is used for rotating the reading values. + + This might not be the same as the screen orientation. For example, in the FixedOrientation mode, + the reading values are not rotated, and therefore the property is 0. + + In the UserOrientation mode, the readings are rotated based on the userOrientation property, + and therefore this property is equal to the userOrientation property. + + In the AutomaticOrientation mode, the readings are rotated based on the screen orientation, + and therefore this property will be equal to the current screen orientation. + + This property is set by the backend and only valid for orientable sensors. +*/ + +int QSensor::currentOrientation() const +{ + Q_D(const QSensor); + return d->currentOrientation; +} + +/*! + \since 5.1 + Sets the current screen orientation to \a currentOrientation. This is to be called from the + backend whenever the screen orientation or the userOrientation property changes. +*/ +void QSensor::setCurrentOrientation(int currentOrientation) +{ + Q_D(QSensor); + if (d->currentOrientation != currentOrientation) { + d->currentOrientation = currentOrientation; + emit currentOrientationChanged(currentOrientation); + } +} + +/*! + \property QSensor::userOrientation + \since 5.1 + \brief The angle used for rotating the reading values in the UserOrientation mode. + + When the axesOrientationMode property is set to UserOrientation, the angle for rotating the + reading values is taken from this property. In other modes, the property has no effect. + + The default is 0. The only valid values are 0, 90, 180 and 270, as those are the only possible + screen orientations. + + This property is only valid for orientable sensors. +*/ + +int QSensor::userOrientation() const +{ + Q_D(const QSensor); + return d->userOrientation; +} + +void QSensor::setUserOrientation(int userOrientation) +{ + Q_D(QSensor); + if (d->userOrientation != userOrientation) { + d->userOrientation = userOrientation; + emit userOrientationChanged(userOrientation); + } +} + +/*! \fn QSensor::sensorError(int error) This signal is emitted when an \a error code is set on the sensor. diff --git a/src/sensors/qsensor.h b/src/sensors/qsensor.h index f7162753..45d1aa3c 100644 --- a/src/sensors/qsensor.h +++ b/src/sensors/qsensor.h @@ -80,6 +80,7 @@ class Q_SENSORS_EXPORT QSensor : public QObject Q_OBJECT Q_ENUMS(Feature) + Q_ENUMS(AxesOrientationMode) Q_PROPERTY(QByteArray identifier READ identifier WRITE setIdentifier) Q_PROPERTY(QByteArray type READ type) Q_PROPERTY(bool connectedToBackend READ isConnectedToBackend) @@ -94,6 +95,9 @@ class Q_SENSORS_EXPORT QSensor : public QObject Q_PROPERTY(int error READ error NOTIFY sensorError) Q_PROPERTY(bool alwaysOn READ isAlwaysOn WRITE setAlwaysOn NOTIFY alwaysOnChanged REVISION 1) Q_PROPERTY(bool skipDuplicates READ skipDuplicates WRITE setSkipDuplicates NOTIFY skipDuplicatesChanged) + Q_PROPERTY(AxesOrientationMode axesOrientationMode READ axesOrientationMode WRITE setAxesOrientationMode NOTIFY axesOrientationModeChanged) + Q_PROPERTY(int currentOrientation READ currentOrientation NOTIFY currentOrientationChanged) + Q_PROPERTY(int userOrientation READ userOrientation WRITE setUserOrientation NOTIFY userOrientationChanged) #ifdef Q_QDOC Q_PROPERTY(int maxBufferSize) Q_PROPERTY(int efficientBufferSize) @@ -107,9 +111,17 @@ public: FieldOfView, AccelerationMode, SkipDuplicates, + AxesOrientation, Reserved = 257 // Make sure at least 2 bytes are used for the enum to avoid breaking BC later }; + // Keep in sync with QmlSensor::AxesOrientationMode + enum AxesOrientationMode { + FixedOrientation, + AutomaticOrientation, + UserOrientation + }; + explicit QSensor(const QByteArray &type, QObject *parent = 0); virtual ~QSensor(); @@ -159,6 +171,15 @@ public: Q_INVOKABLE bool isFeatureSupported(Feature feature) const; + AxesOrientationMode axesOrientationMode() const; + void setAxesOrientationMode(AxesOrientationMode axesOrientationMode); + + int currentOrientation() const; + void setCurrentOrientation(int currentOrientation); + + int userOrientation() const; + void setUserOrientation(int userOrientation); + public Q_SLOTS: // Start receiving values from the sensor bool start(); @@ -175,6 +196,9 @@ Q_SIGNALS: void alwaysOnChanged(); void dataRateChanged(); void skipDuplicatesChanged(bool skipDuplicates); + void axesOrientationModeChanged(AxesOrientationMode axesOrientationMode); + void currentOrientationChanged(int currentOrientation); + void userOrientationChanged(int userOrientation); protected: explicit QSensor(const QByteArray &type, QSensorPrivate &dd, QObject* parent = 0); diff --git a/src/sensors/qsensor_p.h b/src/sensors/qsensor_p.h index 8504a3f6..041e4baa 100644 --- a/src/sensors/qsensor_p.h +++ b/src/sensors/qsensor_p.h @@ -80,6 +80,9 @@ public: , error(0) , alwaysOn(false) , skipDuplicates(false) + , axesOrientationMode(QSensor::FixedOrientation) + , currentOrientation(0) + , userOrientation(0) { } @@ -110,6 +113,10 @@ public: bool alwaysOn; bool skipDuplicates; + + QSensor::AxesOrientationMode axesOrientationMode; + int currentOrientation; + int userOrientation; }; class QSensorReadingPrivate |