From 164e4f5813d8beb30ce8e1555f49f84b785c0d51 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 9 Jun 2011 18:31:09 +1000 Subject: Add dummy, generic and simulator backend The Simulator backend is not working/tested at this stage as the simulator library is not available for Qt5 at this stage. In addtion the sensor_explorer test app was added for simple sensor testing. --- tests/manual/sensor_explorer/explorer.cpp | 444 +++++++++++++++++++++++ tests/manual/sensor_explorer/explorer.h | 84 +++++ tests/manual/sensor_explorer/explorer.ui | 406 +++++++++++++++++++++ tests/manual/sensor_explorer/main.cpp | 50 +++ tests/manual/sensor_explorer/sensor_explorer.pro | 16 + tests/tests.pro | 2 + 6 files changed, 1002 insertions(+) create mode 100644 tests/manual/sensor_explorer/explorer.cpp create mode 100644 tests/manual/sensor_explorer/explorer.h create mode 100644 tests/manual/sensor_explorer/explorer.ui create mode 100644 tests/manual/sensor_explorer/main.cpp create mode 100644 tests/manual/sensor_explorer/sensor_explorer.pro create mode 100644 tests/tests.pro (limited to 'tests') diff --git a/tests/manual/sensor_explorer/explorer.cpp b/tests/manual/sensor_explorer/explorer.cpp new file mode 100644 index 00000000..31308379 --- /dev/null +++ b/tests/manual/sensor_explorer/explorer.cpp @@ -0,0 +1,444 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "explorer.h" +#include +#include +#include +#include +#include + +Explorer::Explorer(QWidget *parent) + : QMainWindow(parent) + , m_sensor(0) + , ignoreItemChanged(false) +{ + ui.setupUi(this); + // Clear out example data from the .ui file + ui.sensors->clear(); + clearSensorProperties(); + clearReading(); + + // Force types to be registered + (void)QSensor::sensorTypes(); + // Listen for changes to the registered types + QSensor *sensor = new QSensor(QByteArray(), this); + connect(sensor, SIGNAL(availableSensorsChanged()), this, SLOT(loadSensors())); +} + +Explorer::~Explorer() +{ +} + +void Explorer::loadSensors() +{ + qDebug() << "Explorer::loadSensors"; + + // Clear out anything that's in there now + ui.sensors->clear(); + + foreach (const QByteArray &type, QSensor::sensorTypes()) { + qDebug() << "Found type" << type; + foreach (const QByteArray &identifier, QSensor::sensorsForType(type)) { + qDebug() << "Found identifier" << identifier; + // Don't put in sensors we can't connect to + QSensor sensor(type); + sensor.setIdentifier(identifier); + if (!sensor.connectToBackend()) { + qDebug() << "Couldn't connect to" << identifier; + continue; + } + + qDebug() << "Adding identifier" << identifier; + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << QString::fromLatin1(identifier)); + item->setData(0, Qt::UserRole, QString::fromLatin1(type)); + ui.sensors->addTopLevelItem(item); + } + } + + if (ui.sensors->topLevelItemCount() == 0) { + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << tr("No Sensors Found")); + item->setData(0, Qt::UserRole, QString()); + ui.sensors->addTopLevelItem(item); + } + + ui.sensors->setCurrentItem(0); + ui.scrollArea->hide(); + + resizeSensors(); +} + +void Explorer::resizeSensors() +{ + ui.sensors->resizeColumnToContents(0); + int length = ui.sensors->header()->length() + 4; + ui.sensors->setFixedWidth(length); +} + +void Explorer::on_sensors_currentItemChanged() +{ + qDebug() << "Explorer::sensorSelected"; + + // Clear out anything that's in there now + if (m_sensor) { + delete m_sensor; + m_sensor = 0; + } + clearSensorProperties(); + clearReading(); + ui.scrollArea->hide(); + + // Check that we've selected an item + QTreeWidgetItem *item = ui.sensors->currentItem(); + if (!item) { + qWarning() << "Didn't select an item!"; + return; + } + + QByteArray type = item->data(0, Qt::UserRole).toString().toLatin1(); + QByteArray identifier = item->data(0, Qt::DisplayRole).toString().toLatin1(); + + if (type.isEmpty()) { + // Uh oh, there aren't any sensors. + // The user has clicked the dummy list entry so just ignore it. + return; + } + + // Connect to the sensor so we can probe it + m_sensor = new QSensor(type, this); + connect(m_sensor, SIGNAL(readingChanged()), this, SLOT(sensor_changed())); + m_sensor->setIdentifier(identifier); + if (!m_sensor->connectToBackend()) { + delete m_sensor; + m_sensor = 0; + qWarning() << "Can't connect to the sensor!"; + return; + } + + ui.scrollArea->show(); + loadSensorProperties(); + loadReading(); + + adjustTableColumns(ui.sensorprops); + adjustTableColumns(ui.reading); + QTimer::singleShot(100, this, SLOT(adjustSizes())); +} + +void Explorer::clearReading() +{ + ui.reading->setRowCount(0); +} + +void Explorer::loadReading() +{ + // Probe the reading using Qt's meta-object facilities + QSensorReading *reading = m_sensor->reading(); + const QMetaObject *mo = reading->metaObject(); + int firstProperty = QSensorReading::staticMetaObject.propertyOffset(); + + ui.reading->setRowCount(mo->propertyCount() - firstProperty); + + for (int i = firstProperty; i < mo->propertyCount(); ++i) { + int row = i - firstProperty; + QTableWidgetItem *index; + if (row == 0) + // timestamp is not available via index + index = new QTableWidgetItem(QLatin1String("N/A")); + else + index = new QTableWidgetItem(QVariant(row - 1).toString()); + QTableWidgetItem *prop = new QTableWidgetItem(mo->property(i).name()); + QString typeName = QLatin1String(mo->property(i).typeName()); + int crap = typeName.lastIndexOf("::"); + if (crap != -1) + typeName = typeName.mid(crap + 2); + QTableWidgetItem *type = new QTableWidgetItem(typeName); + QTableWidgetItem *value = new QTableWidgetItem(); + + index->setFlags(value->flags() ^ Qt::ItemIsEditable); + prop->setFlags(value->flags() ^ Qt::ItemIsEditable); + type->setFlags(value->flags() ^ Qt::ItemIsEditable); + value->setFlags(value->flags() ^ Qt::ItemIsEditable); + + ui.reading->setItem(row, 0, index); + ui.reading->setItem(row, 1, prop); + ui.reading->setItem(row, 2, type); + ui.reading->setItem(row, 3, value); + } +} + +void Explorer::clearSensorProperties() +{ + ui.sensorprops->setRowCount(0); +} + +void Explorer::loadSensorProperties() +{ + ignoreItemChanged = true; + + // Probe the sensor using Qt's meta-object facilities + const QMetaObject *mo = m_sensor->metaObject(); + int firstProperty = QSensor::staticMetaObject.propertyOffset(); + + int rows = mo->propertyCount() - firstProperty; + ui.sensorprops->setRowCount(rows); + + int offset = 0; + for (int i = firstProperty; i < mo->propertyCount(); ++i) { + int row = i - firstProperty - offset; + QLatin1String name(mo->property(i).name()); + if (name == "sensorid" || + //name == "type" || + name == "reading" || + name == "connected" || + name == "running" || + name == "supportsPolling") { + ++offset; + continue; + } + QTableWidgetItem *prop = new QTableWidgetItem(name); + QString typeName = QLatin1String(mo->property(i).typeName()); + int crap = typeName.lastIndexOf("::"); + if (crap != -1) + typeName = typeName.mid(crap + 2); + QTableWidgetItem *type = new QTableWidgetItem(typeName); + QVariant v = mo->property(i).read(m_sensor); + QString val; + if (typeName == "qrangelist") { + qrangelist rl = v.value(); + QStringList out; + foreach (const qrange &r, rl) { + if (r.first == r.second) + out << QString("%1 Hz").arg(r.first); + else + out << QString("%1-%2 Hz").arg(r.first).arg(r.second); + } + val = out.join(", "); + } else if (typeName == "qoutputrangelist") { + qoutputrangelist rl = v.value(); + QStringList out; + foreach (const qoutputrange &r, rl) { + out << QString("(%1, %2) += %3").arg(r.minimum).arg(r.maximum).arg(r.accuracy); + } + val = out.join(", "); + } else { + val = v.toString(); + } + QTableWidgetItem *value = new QTableWidgetItem(val); + + prop->setFlags(value->flags() ^ Qt::ItemIsEditable); + type->setFlags(value->flags() ^ Qt::ItemIsEditable); + if (!mo->property(i).isWritable()) { + // clear the editable flag + value->setFlags(value->flags() ^ Qt::ItemIsEditable); + } + + ui.sensorprops->setItem(row, 0, prop); + ui.sensorprops->setItem(row, 1, type); + ui.sensorprops->setItem(row, 2, value); + } + + // We don't add all properties + ui.sensorprops->setRowCount(rows - offset); + + ignoreItemChanged = false; +} + +void Explorer::showEvent(QShowEvent *event) +{ + // Once we're visible, load the sensors + // (don't delay showing the UI while we load plugins, connect to backends, etc.) + QTimer::singleShot(0, this, SLOT(loadSensors())); + + QMainWindow::showEvent(event); +} + +// Resize columns to fit the space. +// This shouldn't be so hard! +void Explorer::adjustTableColumns(QTableWidget *table) +{ + if (table->rowCount() == 0) { + table->setFixedHeight(0); + return; + } + + // At least this is easy to do + table->resizeColumnsToContents(); + int length = table->verticalHeader()->length(); + length += (length / static_cast(table->verticalHeader()->count())); // Add 1 more (the header itself) + table->setFixedHeight(length); + + int columns = table->columnCount(); + QList width; + int suggestedWidth = 0; + for (int i = 0; i < columns; ++i) { + int cwidth = table->columnWidth(i); + width << cwidth; + suggestedWidth += cwidth; + } + + int actualWidth = table->size().width(); + //qDebug() << "suggestedWidth" << suggestedWidth << "actualWidth" << actualWidth; + + // We only scale the columns up, we don't scale down + if (actualWidth <= suggestedWidth) + return; + + qreal multiplier = actualWidth / static_cast(suggestedWidth); + int currentSpace = 4; + for (int i = 0; i < columns; ++i) { + width[i] = multiplier * width[i]; + currentSpace += width[i]; + } + + // It ends up too big due to cell decorations or something. + // Make things smaller one pixel at a time in round robin fashion until we're good. + int i = 0; + while (currentSpace > actualWidth) { + --width[i]; + --currentSpace; + i = (i + 1) % columns; + } + + for (int i = 0; i < columns; ++i) { + table->setColumnWidth(i, width[i]); + } + + table->setMinimumWidth(suggestedWidth); +} + +void Explorer::adjustSizes() +{ + adjustTableColumns(ui.reading); + adjustTableColumns(ui.sensorprops); +} + +void Explorer::resizeEvent(QResizeEvent *event) +{ + resizeSensors(); + adjustSizes(); + + QMainWindow::resizeEvent(event); +} + +void Explorer::on_start_clicked() +{ + m_sensor->start(); + QTimer::singleShot(0, this, SLOT(loadSensorProperties())); +} + +void Explorer::on_stop_clicked() +{ + m_sensor->stop(); + QTimer::singleShot(0, this, SLOT(loadSensorProperties())); +} + +void Explorer::sensor_changed() +{ + QSensorReading *reading = m_sensor->reading(); + filter(reading); +} + +bool Explorer::filter(QSensorReading *reading) +{ + const QMetaObject *mo = reading->metaObject(); + int firstProperty = QSensorReading::staticMetaObject.propertyOffset(); + + for (int i = firstProperty; i < mo->propertyCount(); ++i) { + int row = i - firstProperty; + QString typeName = QLatin1String(mo->property(i).typeName()); + int crap = typeName.lastIndexOf("::"); + if (crap != -1) + typeName = typeName.mid(crap + 2); + QLatin1String name(mo->property(i).name()); + QTableWidgetItem *value = ui.reading->item(row, 3); + QVariant val = mo->property(i).read(reading); + if (typeName == "qtimestamp") { + value->setText(QString("%1").arg(val.value())); + } else if (typeName == "LightLevel") { + QString text; + switch (val.toInt()) { + case 1: + text = "Dark"; + break; + case 2: + text = "Twilight"; + break; + case 3: + text = "Light"; + break; + case 4: + text = "Bright"; + break; + case 5: + text = "Sunny"; + break; + default: + text = "Undefined"; + break; + } + value->setText(text); + } else { + value->setText(val.toString()); + } + } + + adjustTableColumns(ui.reading); + //QTimer::singleShot(0, this, SLOT(adjustSizes())); + + return false; +} + +void Explorer::on_sensorprops_itemChanged(QTableWidgetItem *item) +{ + if (ignoreItemChanged) + return; + if (!(item->flags() & Qt::ItemIsEditable)) + return; + + int row = item->row(); + QString name = ui.sensorprops->item(row, 0)->text(); + QVariant value = item->text(); + + qDebug() << "setProperty" << name << value; + m_sensor->setProperty(name.toLatin1().constData(), QVariant(value)); + + QTimer::singleShot(0, this, SLOT(loadSensorProperties())); +} + diff --git a/tests/manual/sensor_explorer/explorer.h b/tests/manual/sensor_explorer/explorer.h new file mode 100644 index 00000000..fdc3516b --- /dev/null +++ b/tests/manual/sensor_explorer/explorer.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef EXPLORER_H +#define EXPLORER_H + +#include +#include +#include + + +class Explorer : public QMainWindow, public QSensorFilter +{ + Q_OBJECT +public: + Explorer(QWidget *parent = 0); + ~Explorer(); + + bool filter(QSensorReading *reading); + +private slots: + void loadSensors(); + void on_sensors_currentItemChanged(); + void on_sensorprops_itemChanged(QTableWidgetItem *item); + void on_start_clicked(); + void on_stop_clicked(); + void sensor_changed(); + void adjustSizes(); + void loadSensorProperties(); + +private: + void showEvent(QShowEvent *event); + void resizeEvent(QResizeEvent *event); + + void clearReading(); + void loadReading(); + void clearSensorProperties(); + void adjustTableColumns(QTableWidget *table); + void resizeSensors(); + + Ui::Explorer ui; + QSensor *m_sensor; + bool ignoreItemChanged; +}; + +#endif + diff --git a/tests/manual/sensor_explorer/explorer.ui b/tests/manual/sensor_explorer/explorer.ui new file mode 100644 index 00000000..166e9c36 --- /dev/null +++ b/tests/manual/sensor_explorer/explorer.ui @@ -0,0 +1,406 @@ + + + Explorer + + + + 0 + 0 + 760 + 636 + + + + + 0 + 0 + + + + MainWindow + + + + + 9 + + + + + Sensors that were detected on the device are listed in the list on the left, grouped by type. The reading properties for the sensor will be presented on the right. + + + Qt::AutoText + + + true + + + + + + + + 9 + + + 0 + + + + + + 9 + + + 0 + + + + + Sensor + + + sensors + + + + + + + + 0 + 0 + + + + true + + + QAbstractItemView::SelectRows + + + false + + + false + + + false + + + false + + + false + + + + Sensor + + + + + dummy.accelerometer + + + + + + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 477 + 556 + + + + + 9 + + + 0 + + + + + + 0 + 0 + + + + + 9 + + + 0 + + + + + Sensor Properties + + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + true + + + 3 + + + false + + + false + + + + 1 + + + + + Name + + + + + Type + + + + + Value + + + + + supportedIntervals + + + + + qrangelist + + + + + + + + + + + + + + + + + 9 + + + 0 + + + + + start + + + + + + + stop + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 9 + + + 0 + + + + + Reading Properties + + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + true + + + 4 + + + false + + + false + + + + 1 + + + + + 2 + + + + + Index + + + + + Value + + + + + Type + + + + + Value + + + + + 0 + + + + + x + + + + + qreal + + + + + 9.8 + + + + + 0 + + + + + changeOfBeingEaten + + + + + bool + + + + + true + + + + + + + + + + + Qt::Vertical + + + + 0 + 18 + + + + + + + + + + + + + + + + + + diff --git a/tests/manual/sensor_explorer/main.cpp b/tests/manual/sensor_explorer/main.cpp new file mode 100644 index 00000000..63ef1b9d --- /dev/null +++ b/tests/manual/sensor_explorer/main.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "explorer.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + Explorer explorer; + explorer.show(); + return app.exec(); +} + diff --git a/tests/manual/sensor_explorer/sensor_explorer.pro b/tests/manual/sensor_explorer/sensor_explorer.pro new file mode 100644 index 00000000..fc273052 --- /dev/null +++ b/tests/manual/sensor_explorer/sensor_explorer.pro @@ -0,0 +1,16 @@ +TEMPLATE=app +TARGET=sensor_explorer + +QT = core gui sensors + +FORMS=\ + explorer.ui + +HEADERS=\ + explorer.h + +SOURCES=\ + explorer.cpp\ + main.cpp + + diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 00000000..566e1725 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs + -- cgit v1.2.3