#include "explorer.h"
#include <QTimer>
#include <QDebug>
#include <qsensor.h>
#include <QMetaObject>
#include <QMetaProperty>
QTM_USE_NAMESPACE
Explorer::Explorer(QWidget *parent)
: QMainWindow(parent)
, m_sensor(0)
, ignoreItemChanged(false)
{
ui.setupUi(this);
#ifdef MAEMO5
ui.label->hide();
#endif
ui.sensors->clear();
clearSensorProperties();
clearReading();
(void)QSensor::sensorTypes();
QSensor *sensor = new QSensor(QByteArray(), this);
connect(sensor, SIGNAL(availableSensorsChanged()), this, SLOT(loadSensors()));
}
Explorer::~Explorer()
{
}
void Explorer::loadSensors()
{
qDebug() << "Explorer::loadSensors";
ui.sensors->clear();
foreach (const QByteArray &type, QSensor::sensorTypes()) {
qDebug() << "Found type" << type;
foreach (const QByteArray &identifier, QSensor::sensorsForType(type)) {
qDebug() << "Found identifier" << identifier;
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";
if (m_sensor) {
delete m_sensor;
m_sensor = 0;
}
clearSensorProperties();
clearReading();
ui.scrollArea->hide();
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()) {
return;
}
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()
{
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)
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;
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 == "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<qrangelist>();
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<qoutputrangelist>();
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()) {
value->setFlags(value->flags() ^ Qt::ItemIsEditable);
}
ui.sensorprops->setItem(row, 0, prop);
ui.sensorprops->setItem(row, 1, type);
ui.sensorprops->setItem(row, 2, value);
}
ui.sensorprops->setRowCount(rows - offset);
ignoreItemChanged = false;
}
void Explorer::showEvent(QShowEvent *event)
{
QTimer::singleShot(0, this, SLOT(loadSensors()));
QMainWindow::showEvent(event);
}
void Explorer::adjustTableColumns(QTableWidget *table)
{
if (table->rowCount() == 0) {
table->setFixedHeight(0);
return;
}
table->resizeColumnsToContents();
int length = table->verticalHeader()->length();
length += (length / static_cast<qreal>(table->verticalHeader()->count()));
#ifdef MAEMO5
length += 10;
#endif
table->setFixedHeight(length);
int columns = table->columnCount();
QList<int> 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();
if (actualWidth <= suggestedWidth)
return;
qreal multiplier = actualWidth / static_cast<qreal>(suggestedWidth);
int currentSpace = 4;
for (int i = 0; i < columns; ++i) {
width[i] = multiplier * width[i];
currentSpace += width[i];
}
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<qtimestamp>()));
} 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);
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()));
}