|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "explorer.h" |
|
43 #include <QTimer> |
|
44 #include <QDebug> |
|
45 #include <qsensor.h> |
|
46 #include <QMetaObject> |
|
47 #include <QMetaProperty> |
|
48 |
|
49 QTM_USE_NAMESPACE |
|
50 |
|
51 Explorer::Explorer(QWidget *parent) |
|
52 : QMainWindow(parent) |
|
53 { |
|
54 setupUi(this); |
|
55 // Clear out example data from the .ui file |
|
56 m_sensors->clear(); |
|
57 clearReading(); |
|
58 // We need to know when this widget resizes |
|
59 // so we can resize the columns |
|
60 m_reading->installEventFilter(this); |
|
61 } |
|
62 |
|
63 Explorer::~Explorer() |
|
64 { |
|
65 } |
|
66 |
|
67 void Explorer::loadSensors() |
|
68 { |
|
69 qDebug() << "Explorer::loadSensors"; |
|
70 |
|
71 // Clear out anything that's in there now |
|
72 m_sensors->clear(); |
|
73 |
|
74 foreach (const QByteArray &type, QSensor::sensorTypes()) { |
|
75 qDebug() << "Found type" << type; |
|
76 // The type item. We don't add it yet because there may not be any sensors of this type |
|
77 // and we only show types that have sensors available. |
|
78 QTreeWidgetItem *typeItem = new QTreeWidgetItem(QStringList() << QString::fromLatin1(type)); |
|
79 bool added = false; |
|
80 foreach (const QByteArray &identifier, QSensor::sensorsForType(type)) { |
|
81 qDebug() << "Found identifier" << identifier; |
|
82 // Don't put in sensors we can't connect to |
|
83 QSensor sensor; |
|
84 sensor.setType(type); |
|
85 sensor.setIdentifier(identifier); |
|
86 if (!sensor.connect()) { |
|
87 qDebug() << "Couldn't connect to" << identifier; |
|
88 continue; |
|
89 } |
|
90 |
|
91 // Since we're adding a sensor we can go ahead and add the type (unless it has |
|
92 // already been added). |
|
93 if (!added) { |
|
94 qDebug() << "Adding type" << type; |
|
95 m_sensors->addTopLevelItem(typeItem); |
|
96 added = true; |
|
97 } |
|
98 qDebug() << "Adding identifier" << identifier; |
|
99 (void)new QTreeWidgetItem(typeItem, QStringList() << QString::fromLatin1(identifier)); |
|
100 } |
|
101 // Cleanup if we didn't add the type |
|
102 if (!added) { |
|
103 qDebug() << "Didn't add type" << type; |
|
104 delete typeItem; |
|
105 } |
|
106 } |
|
107 |
|
108 // Don't hide stuff |
|
109 m_sensors->expandAll(); |
|
110 } |
|
111 |
|
112 void Explorer::clearReading() |
|
113 { |
|
114 m_reading->setRowCount(0); |
|
115 } |
|
116 |
|
117 void Explorer::loadReading() |
|
118 { |
|
119 qDebug() << "Explorer::loadReading"; |
|
120 |
|
121 // Clear out anything that's in there now |
|
122 clearReading(); |
|
123 |
|
124 // Check that we've selected an item |
|
125 QTreeWidgetItem *item = m_sensors->currentItem(); |
|
126 if (!item) { |
|
127 qWarning() << "Didn't select an item!"; |
|
128 return; |
|
129 } |
|
130 |
|
131 // Check that we've selected a sensor (which has a parent) |
|
132 QTreeWidgetItem *parent = item->parent(); |
|
133 if (!parent) { |
|
134 qWarning() << "Didn't select a sensor!"; |
|
135 return; |
|
136 } |
|
137 |
|
138 QByteArray type = parent->data(0, Qt::DisplayRole).toString().toLatin1(); |
|
139 QByteArray identifier = item->data(0, Qt::DisplayRole).toString().toLatin1(); |
|
140 |
|
141 // Connect to the sensor so we can probe it |
|
142 QSensor sensor; |
|
143 sensor.setType(type); |
|
144 sensor.setIdentifier(identifier); |
|
145 if (!sensor.connect()) { |
|
146 qWarning() << "Can't connect to the sensor!"; |
|
147 return; |
|
148 } |
|
149 |
|
150 // Probe the reading using Qt's meta-object facilities |
|
151 QSensorReading *reading = sensor.reading(); |
|
152 const QMetaObject *mo = reading->metaObject(); |
|
153 int firstProperty = QSensorReading::staticMetaObject.propertyOffset(); |
|
154 |
|
155 m_reading->setRowCount(mo->propertyCount() - firstProperty); |
|
156 |
|
157 for(int i = firstProperty; i < mo->propertyCount(); ++i) { |
|
158 int row = i - firstProperty; |
|
159 QTableWidgetItem *index; |
|
160 if (row == 0) |
|
161 // timestamp is not available via index |
|
162 index = new QTableWidgetItem(QLatin1String("N/A")); |
|
163 else |
|
164 index = new QTableWidgetItem(QVariant(row - 1).toString()); |
|
165 QTableWidgetItem *prop = new QTableWidgetItem(mo->property(i).name()); |
|
166 QTableWidgetItem *type = new QTableWidgetItem(mo->property(i).typeName()); |
|
167 m_reading->setItem(row, 0, index); |
|
168 m_reading->setItem(row, 1, prop); |
|
169 m_reading->setItem(row, 2, type); |
|
170 } |
|
171 |
|
172 adjustReadingColumns(); |
|
173 } |
|
174 |
|
175 void Explorer::showEvent(QShowEvent *event) |
|
176 { |
|
177 // Once we're visible, load the sensors |
|
178 // (don't delay showing the UI while we load plugins, connect to backends, etc.) |
|
179 QTimer::singleShot(0, this, SLOT(loadSensors())); |
|
180 |
|
181 QMainWindow::showEvent(event); |
|
182 } |
|
183 |
|
184 // Resize columns to fit the space. |
|
185 // This shouldn't be so hard! |
|
186 void Explorer::adjustReadingColumns() |
|
187 { |
|
188 // At least this is easy to do |
|
189 m_reading->resizeColumnsToContents(); |
|
190 |
|
191 int indexWidth = m_reading->columnWidth(0); |
|
192 int propWidth = m_reading->columnWidth(1); |
|
193 int typeWidth = m_reading->columnWidth(2); |
|
194 |
|
195 int suggestedWidth = indexWidth + propWidth + typeWidth; |
|
196 int actualWidth = m_reading->size().width(); |
|
197 //qDebug() << "suggestedWidth" << suggestedWidth << "actualWidth" << actualWidth; |
|
198 |
|
199 // We only scale the columns up, we don't scale down |
|
200 if (actualWidth <= suggestedWidth) |
|
201 return; |
|
202 |
|
203 qreal multiplier = actualWidth / static_cast<qreal>(suggestedWidth); |
|
204 indexWidth = multiplier * indexWidth; |
|
205 propWidth = multiplier * propWidth; |
|
206 typeWidth = multiplier * typeWidth; |
|
207 |
|
208 // It ends up too big due to cell decorations or something. |
|
209 // Make things smaller one pixel at a time in round robin fashion until we're good. |
|
210 int currentSpace = indexWidth + propWidth + typeWidth + 4; |
|
211 while (actualWidth < currentSpace) { |
|
212 if (actualWidth < currentSpace) { |
|
213 --indexWidth; |
|
214 --currentSpace; |
|
215 } |
|
216 if (actualWidth < currentSpace) { |
|
217 --propWidth; |
|
218 --currentSpace; |
|
219 } |
|
220 if (actualWidth < currentSpace) { |
|
221 --typeWidth; |
|
222 --currentSpace; |
|
223 } |
|
224 } |
|
225 |
|
226 m_reading->setColumnWidth(0, indexWidth); |
|
227 m_reading->setColumnWidth(1, propWidth); |
|
228 m_reading->setColumnWidth(2, typeWidth); |
|
229 } |
|
230 |
|
231 bool Explorer::eventFilter(QObject *obj, QEvent *event) |
|
232 { |
|
233 if (obj == m_reading && event->type() == QEvent::Resize) { |
|
234 // If the table resizes, adjust the column sizes automatically |
|
235 adjustReadingColumns(); |
|
236 } |
|
237 |
|
238 return QMainWindow::eventFilter(obj, event); |
|
239 } |
|
240 |