#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()));
 }