Merge lp:~veebers/autopilot-qt/enable-datamodel-elements into lp:autopilot-qt
- enable-datamodel-elements
- Merge into trunk
Proposed by
Christopher Lee
Status: | Merged |
---|---|
Merged at revision: | 87 |
Proposed branch: | lp:~veebers/autopilot-qt/enable-datamodel-elements |
Merge into: | lp:autopilot-qt |
Diff against target: |
1061 lines (+687/-91) 8 files modified
driver/dbus_object.cpp (+8/-8) driver/introspection.cpp (+5/-5) driver/introspection.h (+2/-2) driver/qtnode.cpp (+551/-58) driver/qtnode.h (+117/-14) driver/rootnode.cpp (+2/-2) driver/rootnode.h (+1/-1) tests/unittests/tst_introspection.cpp (+1/-1) |
To merge this branch: | bzr merge lp:~veebers/autopilot-qt/enable-datamodel-elements |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards (community) | Needs Fixing | ||
Review via email: mp+223853@code.launchpad.net |
Commit message
Remove QtNode and use DBusNode interface to extend the possible supported node types to include those that don't inherit from QObject.
Description of the change
Remove QtNode and replace with DBusNode Interface to extend the possible node types to those that don't inherit from QObject.
What was QtNode is now QObjectNode. We now also have QModelIndexNode, QTableWidgetIte
To post a comment you must log in.
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
review:
Needs Fixing
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'driver/dbus_object.cpp' |
2 | --- driver/dbus_object.cpp 2014-03-12 13:26:27 +0000 |
3 | +++ driver/dbus_object.cpp 2014-06-20 04:04:19 +0000 |
4 | @@ -23,15 +23,15 @@ |
5 | #include <QDBusConnection> |
6 | #include <QThread> |
7 | |
8 | -QtNode::Ptr GetNodeWithId(int object_id) |
9 | +DBusNode::Ptr GetNodeWithId(int object_id) |
10 | { |
11 | QString query = QString("//*[id=%1]").arg(object_id); |
12 | - QList<QtNode::Ptr> objects = GetNodesThatMatchQuery(query); |
13 | + QList<DBusNode::Ptr> objects = GetNodesThatMatchQuery(query); |
14 | |
15 | if (objects.isEmpty()) |
16 | { |
17 | qWarning() << "No Object with with id" << object_id << "found in object tree."; |
18 | - return QtNode::Ptr(); |
19 | + return DBusNode::Ptr(); |
20 | } |
21 | |
22 | return objects.at(0); |
23 | @@ -64,7 +64,8 @@ |
24 | return; |
25 | } |
26 | |
27 | - QtNode::Ptr node = GetNodeWithId(object_id); |
28 | + std::shared_ptr<const QObjectNode> node = std::dynamic_pointer_cast<const QObjectNode>(GetNodeWithId(object_id)); |
29 | + |
30 | if (! node) |
31 | { |
32 | qWarning() << "Unable to register signal interest."; |
33 | @@ -125,7 +126,7 @@ |
34 | |
35 | void DBusObject::ListSignals(int object_id, const QDBusMessage& message) |
36 | { |
37 | - QtNode::Ptr node = GetNodeWithId(object_id); |
38 | + std::shared_ptr<const QObjectNode> node = std::dynamic_pointer_cast<const QObjectNode>(GetNodeWithId(object_id)); |
39 | QDBusMessage reply = message.createReply(); |
40 | if (! node) |
41 | { |
42 | @@ -163,7 +164,7 @@ |
43 | void DBusObject::ListMethods(int object_id, const QDBusMessage &message) |
44 | { |
45 | QDBusMessage reply = message.createReply(); |
46 | - QtNode::Ptr node = GetNodeWithId(object_id); |
47 | + std::shared_ptr<const QObjectNode> node = std::dynamic_pointer_cast<const QObjectNode>(GetNodeWithId(object_id)); |
48 | if (! node) |
49 | { |
50 | qWarning() << "No Object found while listing methods."; |
51 | @@ -201,7 +202,7 @@ |
52 | { |
53 | Q_UNUSED(message); |
54 | |
55 | - QtNode::Ptr node = GetNodeWithId(object_id); |
56 | + std::shared_ptr<const QObjectNode> node = std::dynamic_pointer_cast<const QObjectNode>(GetNodeWithId(object_id)); |
57 | if (! node) |
58 | { |
59 | qWarning() << "No Object found."; |
60 | @@ -303,4 +304,3 @@ |
61 | |
62 | QDBusConnection::sessionBus().send(msg); |
63 | } |
64 | - |
65 | |
66 | === modified file 'driver/introspection.cpp' |
67 | --- driver/introspection.cpp 2014-03-12 13:26:27 +0000 |
68 | +++ driver/introspection.cpp 2014-06-20 04:04:19 +0000 |
69 | @@ -51,8 +51,8 @@ |
70 | QList<NodeIntrospectionData> Introspect(QString const& query_string) |
71 | { |
72 | QList<NodeIntrospectionData> state; |
73 | - QList<QtNode::Ptr> node_list = GetNodesThatMatchQuery(query_string); |
74 | - foreach (QtNode::Ptr obj, node_list) |
75 | + QList<DBusNode::Ptr> node_list = GetNodesThatMatchQuery(query_string); |
76 | + foreach (DBusNode::Ptr obj, node_list) |
77 | { |
78 | state.append(obj->GetIntrospectionData()); |
79 | } |
80 | @@ -62,7 +62,7 @@ |
81 | } |
82 | |
83 | |
84 | -QList<QtNode::Ptr> GetNodesThatMatchQuery(QString const& query_string) |
85 | +QList<DBusNode::Ptr> GetNodesThatMatchQuery(QString const& query_string) |
86 | { |
87 | #ifdef QT5_SUPPORT |
88 | std::shared_ptr<RootNode> root = std::make_shared<RootNode>(QApplication::instance()); |
89 | @@ -84,13 +84,13 @@ |
90 | root->AddChild((QObject*) widget); |
91 | } |
92 | #endif |
93 | - QList<QtNode::Ptr> node_list; |
94 | + QList<DBusNode::Ptr> node_list; |
95 | |
96 | xpathselect::NodeVector list = xpathselect::SelectNodes(root, query_string.toStdString()); |
97 | for (auto node : list) |
98 | { |
99 | // node may be our root node wrapper *or* an ordinary qobject wrapper |
100 | - auto object_ptr = std::static_pointer_cast<const QtNode>(node); |
101 | + auto object_ptr = std::static_pointer_cast<const DBusNode>(node); |
102 | if (object_ptr) |
103 | { |
104 | node_list.append(object_ptr); |
105 | |
106 | === modified file 'driver/introspection.h' |
107 | --- driver/introspection.h 2014-03-12 13:26:27 +0000 |
108 | +++ driver/introspection.h 2014-06-20 04:04:19 +0000 |
109 | @@ -16,8 +16,8 @@ |
110 | /// Introspect 'obj' and return it's properties in a QVariantMap. |
111 | QList<NodeIntrospectionData> Introspect(const QString& query_string); |
112 | |
113 | -/// Get a list of QtNode pointers that match the given query. |
114 | -QList<QtNode::Ptr> GetNodesThatMatchQuery(QString const& query_string); |
115 | +/// Get a list of DBusNode pointers that match the given query. |
116 | +QList<DBusNode::Ptr> GetNodesThatMatchQuery(QString const& query_string); |
117 | |
118 | /// Return true if 't' is a type that we can marshall over DBus |
119 | QVariant PackProperty(QVariant const& prop); |
120 | |
121 | === modified file 'driver/qtnode.cpp' |
122 | --- driver/qtnode.cpp 2014-03-12 13:26:27 +0000 |
123 | +++ driver/qtnode.cpp 2014-06-20 04:04:19 +0000 |
124 | @@ -17,6 +17,25 @@ |
125 | #endif |
126 | #include <QDBusArgument> |
127 | |
128 | +#include <QAbstractItemView> |
129 | +#include <QAbstractProxyModel> |
130 | +#include <QTableWidget> |
131 | +#include <QTreeView> |
132 | +#include <QTreeWidget> |
133 | +#include <QListView> |
134 | + |
135 | +const QByteArray AP_ID_NAME("_autopilot_id"); |
136 | + |
137 | +void GetTableWidgetChildren(QObject* table_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent); |
138 | +void GetTreeViewChildren(QObject* tree_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent); |
139 | +void GetTreeWidgetChildren(QObject* tree_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent); |
140 | +void GetListViewChildren(QObject* tree_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent); |
141 | + |
142 | +void CollectAllIndexes(QModelIndex index, QAbstractItemModel *model, QModelIndexList &collection); |
143 | +QVariant SafePackProperty(QVariant const& prop); |
144 | + |
145 | +bool MatchProperty(const QVariantMap& packed_properties, const QString& name, QVariant& value); |
146 | + |
147 | // Marshall the NodeIntrospectionData data into a D-Bus argument |
148 | QDBusArgument &operator<<(QDBusArgument &argument, const NodeIntrospectionData &node_data) |
149 | { |
150 | @@ -35,9 +54,169 @@ |
151 | return argument; |
152 | } |
153 | |
154 | -const QByteArray AP_ID_NAME("_autopilot_id"); |
155 | - |
156 | -QtNode::QtNode(QObject *obj, QtNode::Ptr parent) |
157 | +void GetTableWidgetChildren(QObject *table_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent) |
158 | +{ |
159 | + QTableWidget* table = qobject_cast<QTableWidget *>(table_obj); |
160 | + if(! table) { |
161 | + qDebug() << "Unable to cast object to QTableWidget (even though it apparently inherits from it)"; |
162 | + } |
163 | + |
164 | + QList<QTableWidgetItem *> tablewidgetitems = table->findItems("*", Qt::MatchWildcard|Qt::MatchRecursive); |
165 | + foreach (QTableWidgetItem *item, tablewidgetitems){ |
166 | + // std::make_shared<QTableWidgetItemNode>(item, this->shared_from_this()) |
167 | + children.push_back( |
168 | + std::make_shared<QTableWidgetItemNode>(item, parent) |
169 | + ); |
170 | + } |
171 | +} |
172 | + |
173 | +void CollectAllIndexes(QModelIndex index, QAbstractItemModel *model, QModelIndexList &collection) |
174 | +{ |
175 | + // Is there a decent way for me to determine infinite recursion. |
176 | + // The interviews example breaks this code as it just continues creating new children. |
177 | + for(int c=0; c < model->columnCount(index); ++c) { |
178 | + for(int r=0; r < model->rowCount(index); ++r) { |
179 | + QModelIndex new_index = model->index(r, c, index); |
180 | + collection.push_back(new_index); |
181 | + // actually the hashing should never be the same |
182 | + if(qHash(new_index) != qHash(index)) { |
183 | + CollectAllIndexes(new_index, model, collection); |
184 | + } |
185 | + } |
186 | + } |
187 | +} |
188 | + |
189 | +// Pack property, but return a default blank if the packed property is invalid. |
190 | +QVariant SafePackProperty(QVariant const& prop) |
191 | +{ |
192 | + static QVariant blank_default = PackProperty(""); |
193 | + |
194 | + QVariant property_attempt = PackProperty(prop); |
195 | + if(property_attempt.isValid()) |
196 | + return property_attempt; |
197 | + else |
198 | + return blank_default; |
199 | +} |
200 | + |
201 | +bool MatchProperty(const QVariantMap& packed_properties, const QString& name, QVariant& value) |
202 | +{ |
203 | + if (! packed_properties.contains(name)) |
204 | + return false; |
205 | + |
206 | + // Because the properties are packed, we need the value, not the type. |
207 | + QVariant object_value = qvariant_cast<QVariantList>(packed_properties[name]).at(1); |
208 | + if (value.canConvert(object_value.type())) |
209 | + { |
210 | + value.convert(object_value.type()); |
211 | + return value == object_value; |
212 | + } |
213 | + return false; |
214 | +} |
215 | + |
216 | + |
217 | +void GetTreeViewChildren(QObject* tree_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent) |
218 | +{ |
219 | + QTreeView* tree_view = qobject_cast<QTreeView *>(tree_obj); |
220 | + if(! tree_view) { |
221 | + qDebug() << "Unable to cast object to QTreeView (even though it apparently inherits from it)"; |
222 | + return; |
223 | + } |
224 | + |
225 | + QAbstractItemModel* abstract_model = tree_view->model(); |
226 | + if(! abstract_model) |
227 | + { |
228 | + qDebug() << "Unable to retrieve model for QTreeView"; |
229 | + return; |
230 | + } |
231 | + |
232 | + QModelIndexList all_of_them; |
233 | + for(int c=0; c < abstract_model->columnCount(); ++c) { |
234 | + for(int r=0; r < abstract_model->rowCount(); ++r) { |
235 | + QModelIndex index = abstract_model->index(r, c); |
236 | + all_of_them.push_back(index); |
237 | + CollectAllIndexes(index, abstract_model, all_of_them); |
238 | + } |
239 | + } |
240 | + |
241 | + foreach(QModelIndex index, all_of_them) |
242 | + { |
243 | + if(index.isValid()) |
244 | + { |
245 | + children.push_back( |
246 | + std::make_shared<QModelIndexNode>( |
247 | + index, |
248 | + tree_view, |
249 | + parent) |
250 | + ); |
251 | + } |
252 | + } |
253 | +} |
254 | + |
255 | +void GetTreeWidgetChildren(QObject* tree_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent) |
256 | +{ |
257 | + QTreeWidget* tree_widget = qobject_cast<QTreeWidget *>(tree_obj); |
258 | + if(! tree_widget) { |
259 | + qDebug() << "Unable to cast object to QTreeWidget (even though it apparently inherits from it)"; |
260 | + return; |
261 | + } |
262 | + |
263 | + // Lets grab all the top-level elements, they can get their own childnren. |
264 | + for(int i=0; i < tree_widget->topLevelItemCount(); ++i) { |
265 | + children.push_back( |
266 | + std::make_shared<QTreeWidgetItemNode>( |
267 | + tree_widget->topLevelItem(i), |
268 | + parent) |
269 | + ); |
270 | + } |
271 | +} |
272 | + |
273 | +// This coul probably be wrapped up into an AbstractItemView as could |
274 | +// the above TreeView stuff |
275 | +void GetListViewChildren(QObject* list_obj, xpathselect::NodeVector& children, DBusNode::Ptr parent) |
276 | +{ |
277 | + QListView* list_view = qobject_cast<QListView *>(list_obj); |
278 | + if(! list_view) { |
279 | + qDebug() << "Unable to cast object to QTreeView (even though it apparently inherits from it)"; |
280 | + return; |
281 | + } |
282 | + |
283 | + QAbstractItemModel* abstract_model = list_view->model(); |
284 | + |
285 | + if(! abstract_model) { |
286 | + qDebug() << "Unable to retrieve model for QTreeView"; |
287 | + return; |
288 | + } |
289 | + |
290 | + QModelIndexList all_of_them; |
291 | + QModelIndex root_index = list_view->rootIndex(); |
292 | + if(root_index.isValid()) { |
293 | + // The root item is the parent item to the view's toplevel items |
294 | + CollectAllIndexes(root_index, abstract_model, all_of_them); |
295 | + } |
296 | + else { |
297 | + for(int c=0; c < abstract_model->columnCount(); ++c) { |
298 | + for(int r=0; r < abstract_model->rowCount(); ++r) { |
299 | + QModelIndex index = abstract_model->index(r, c); |
300 | + all_of_them.push_back(index); |
301 | + CollectAllIndexes(index, abstract_model, all_of_them); |
302 | + } |
303 | + } |
304 | + } |
305 | + |
306 | + foreach(QModelIndex index, all_of_them) { |
307 | + if(index.isValid()) |
308 | + { |
309 | + children.push_back( |
310 | + std::make_shared<QModelIndexNode>( |
311 | + index, |
312 | + list_view, |
313 | + parent) |
314 | + ); |
315 | + } |
316 | + } |
317 | +} |
318 | + |
319 | +QObjectNode::QObjectNode(QObject *obj, DBusNode::Ptr parent) |
320 | : object_(obj) |
321 | , parent_(parent) |
322 | { |
323 | @@ -45,18 +224,18 @@ |
324 | full_path_ = parent_path + "/" + GetName(); |
325 | } |
326 | |
327 | -QtNode::QtNode(QObject* obj) |
328 | +QObjectNode::QObjectNode(QObject* obj) |
329 | : object_(obj) |
330 | { |
331 | full_path_ = "/" + GetName(); |
332 | } |
333 | |
334 | -QObject* QtNode::getWrappedObject() const |
335 | +QObject* QObjectNode::getWrappedObject() const |
336 | { |
337 | return object_; |
338 | } |
339 | |
340 | -NodeIntrospectionData QtNode::GetIntrospectionData() const |
341 | +NodeIntrospectionData QObjectNode::GetIntrospectionData() const |
342 | { |
343 | NodeIntrospectionData data; |
344 | data.object_path = QString::fromStdString(GetPath()); |
345 | @@ -65,7 +244,7 @@ |
346 | return data; |
347 | } |
348 | |
349 | -std::string QtNode::GetName() const |
350 | +std::string QObjectNode::GetName() const |
351 | { |
352 | QString name = object_->metaObject()->className(); |
353 | |
354 | @@ -76,12 +255,12 @@ |
355 | return name.toStdString(); |
356 | } |
357 | |
358 | -std::string QtNode::GetPath() const |
359 | +std::string QObjectNode::GetPath() const |
360 | { |
361 | return full_path_; |
362 | } |
363 | |
364 | -int32_t QtNode::GetId() const |
365 | +int32_t QObjectNode::GetId() const |
366 | { |
367 | // Note: This method is used to assign ids to both the root node (with a QApplication object) and |
368 | // child nodes. This used to be separate code, but now that we export QApplication properties, |
369 | @@ -97,26 +276,16 @@ |
370 | return qvariant_cast<int32_t>(object_->property(AP_ID_NAME)); |
371 | } |
372 | |
373 | -bool QtNode::MatchStringProperty(const std::string& name, const std::string& value) const |
374 | +bool QObjectNode::MatchStringProperty(const std::string& name, const std::string& value) const |
375 | { |
376 | QVariantMap properties = GetNodeProperties(object_); |
377 | |
378 | QString qname = QString::fromStdString(name); |
379 | - if (! properties.contains(qname)) |
380 | - return false; |
381 | - |
382 | - QVariant object_value = qvariant_cast<QVariantList>(properties[qname]).at(1); |
383 | - QVariant check_value(QString::fromStdString(value)); |
384 | - if (check_value.canConvert(object_value.type())) |
385 | - { |
386 | - check_value.convert(object_value.type()); |
387 | - return check_value == object_value; |
388 | - } |
389 | - |
390 | - return false; |
391 | + QVariant qvalue = QVariant(QString::fromStdString(value)); |
392 | + return MatchProperty(properties, qname, qvalue); |
393 | } |
394 | |
395 | -bool QtNode::MatchIntegerProperty(const std::string& name, int32_t value) const |
396 | +bool QObjectNode::MatchIntegerProperty(const std::string& name, int32_t value) const |
397 | { |
398 | if (name == "id") |
399 | return value == GetId(); |
400 | @@ -124,44 +293,42 @@ |
401 | QVariantMap properties = GetNodeProperties(object_); |
402 | |
403 | QString qname = QString::fromStdString(name); |
404 | - if (! properties.contains(qname)) |
405 | - return false; |
406 | - |
407 | - QVariant object_value = qvariant_cast<QVariantList>(properties[qname]).at(1); |
408 | - QVariant check_value(value); |
409 | - if (check_value.canConvert(object_value.type())) |
410 | - { |
411 | - check_value.convert(object_value.type()); |
412 | - return check_value == object_value; |
413 | - } |
414 | - |
415 | - return false; |
416 | + QVariant qvalue = QVariant(value); |
417 | + return MatchProperty(properties, qname, qvalue); |
418 | } |
419 | |
420 | -bool QtNode::MatchBooleanProperty(const std::string& name, bool value) const |
421 | +bool QObjectNode::MatchBooleanProperty(const std::string& name, bool value) const |
422 | { |
423 | QVariantMap properties = GetNodeProperties(object_); |
424 | |
425 | QString qname = QString::fromStdString(name); |
426 | - if (! properties.contains(qname)) |
427 | - return false; |
428 | - |
429 | - QVariant object_value = qvariant_cast<QVariantList>(properties[qname]).at(1); |
430 | - QVariant check_value(value); |
431 | - |
432 | - if (check_value.canConvert(object_value.type())) |
433 | - { |
434 | - check_value.convert(object_value.type()); |
435 | - return check_value == object_value; |
436 | - } |
437 | - |
438 | - return false; |
439 | + QVariant qvalue = QVariant(value); |
440 | + return MatchProperty(properties, qname, qvalue); |
441 | } |
442 | |
443 | -xpathselect::NodeVector QtNode::Children() const |
444 | +xpathselect::NodeVector QObjectNode::Children() const |
445 | { |
446 | xpathselect::NodeVector children; |
447 | |
448 | + // Do special children handling if needed. |
449 | + // Because QTreeWidget inherits from QTreeView check for it first. |
450 | + if(object_->inherits("QTableWidget")) |
451 | + { |
452 | + GetTableWidgetChildren(object_, children, shared_from_this()); |
453 | + } |
454 | + else if(object_->inherits("QTreeWidget")) |
455 | + { |
456 | + GetTreeWidgetChildren(object_, children, shared_from_this()); |
457 | + } |
458 | + else if(object_->inherits("QTreeView")) |
459 | + { |
460 | + GetTreeViewChildren(object_, children, shared_from_this()); |
461 | + } |
462 | + else if(object_->inherits("QListView")) |
463 | + { |
464 | + GetListViewChildren(object_, children, shared_from_this()); |
465 | + } |
466 | + |
467 | #ifdef QT5_SUPPORT |
468 | // Qt5's hierarchy for QML has changed a bit: |
469 | // - On top there's a QQuickView which holds all the QQuick items |
470 | @@ -170,21 +337,21 @@ |
471 | |
472 | QQuickView *view = qobject_cast<QQuickView*>(object_); |
473 | if (view && view->rootObject() != 0) { |
474 | - children.push_back(std::make_shared<QtNode>(view->rootObject(), shared_from_this())); |
475 | + children.push_back(std::make_shared<QObjectNode>(view->rootObject(), shared_from_this())); |
476 | } |
477 | |
478 | QQuickItem* item = qobject_cast<QQuickItem*>(object_); |
479 | if (item) { |
480 | foreach (QQuickItem *childItem, item->childItems()) { |
481 | if (childItem->parentItem() == item) { |
482 | - children.push_back(std::make_shared<QtNode>(childItem, shared_from_this())); |
483 | + children.push_back(std::make_shared<QObjectNode>(childItem, shared_from_this())); |
484 | } |
485 | } |
486 | } else { |
487 | foreach (QObject *child, object_->children()) |
488 | { |
489 | if (child->parent() == object_) |
490 | - children.push_back(std::make_shared<QtNode>(child, shared_from_this())); |
491 | + children.push_back(std::make_shared<QObjectNode>(child, shared_from_this())); |
492 | } |
493 | } |
494 | |
495 | @@ -192,7 +359,7 @@ |
496 | foreach (QObject *child, object_->children()) |
497 | { |
498 | if (child->parent() == object_) |
499 | - children.push_back(std::make_shared<QtNode>(child, shared_from_this())); |
500 | + children.push_back(std::make_shared<QObjectNode>(child, shared_from_this())); |
501 | } |
502 | |
503 | // If our wrapped object is a QGraphicsScene, we need to explicitly grab any child graphics |
504 | @@ -206,7 +373,7 @@ |
505 | { |
506 | QGraphicsObject *obj = item->toGraphicsObject(); |
507 | if (obj && ! obj->parent()) |
508 | - children.push_back(std::make_shared<QtNode>(obj, shared_from_this())); |
509 | + children.push_back(std::make_shared<QObjectNode>(obj, shared_from_this())); |
510 | } |
511 | } |
512 | #endif |
513 | @@ -215,7 +382,333 @@ |
514 | } |
515 | |
516 | |
517 | -xpathselect::Node::Ptr QtNode::GetParent() const |
518 | -{ |
519 | - return parent_; |
520 | +xpathselect::Node::Ptr QObjectNode::GetParent() const |
521 | +{ |
522 | + return parent_; |
523 | +} |
524 | + |
525 | +// QModelIndexNode |
526 | +QModelIndexNode::QModelIndexNode(QModelIndex index, QAbstractItemView* parent_view, DBusNode::Ptr parent) |
527 | + : index_(index) |
528 | + , parent_view_(parent_view) |
529 | + , parent_(parent) |
530 | +{ |
531 | + std::string parent_path = parent ? parent->GetPath() : ""; |
532 | + full_path_ = parent_path + "/" + GetName(); |
533 | +} |
534 | + |
535 | +QModelIndexNode::QModelIndexNode(QModelIndex index, QAbstractItemView* parent_view) |
536 | + : index_(index) |
537 | + , parent_view_(parent_view) |
538 | +{ |
539 | + full_path_ = "/" + GetName(); |
540 | +} |
541 | + |
542 | +NodeIntrospectionData QModelIndexNode::GetIntrospectionData() const |
543 | +{ |
544 | + NodeIntrospectionData data; |
545 | + data.object_path = QString::fromStdString(GetPath()); |
546 | + data.state = GetProperties(); |
547 | + data.state["id"] = PackProperty(GetId()); |
548 | + return data; |
549 | +} |
550 | + |
551 | +QVariantMap QModelIndexNode::GetProperties() const |
552 | +{ |
553 | + QVariantMap properties; |
554 | + const QAbstractItemModel* model = index_.model(); |
555 | + if(model) |
556 | + { |
557 | + // Make an attempt to store the 'text' of a node to be user friendly-ish. |
558 | + QVariant text_property = PackProperty(model->data(index_)); |
559 | + if(text_property.isValid()) |
560 | + properties["text"] = text_property; |
561 | + else |
562 | + properties["text"] = PackProperty(""); |
563 | + |
564 | + // Include any Role data (mung the role name with added "Role") |
565 | + const QHash<int, QByteArray> role_names = model->roleNames(); |
566 | + QMap<int, QVariant> item_data = model->itemData(index_); |
567 | + foreach(int name, role_names.keys()) |
568 | + { |
569 | + if(item_data.contains(name)) { |
570 | + QVariant property = PackProperty(item_data[name]); |
571 | + if(property.isValid()) |
572 | + properties[role_names[name]+"Role"] = property; |
573 | + } |
574 | + else { |
575 | + // Not sure if this should be set as blank or left. |
576 | + properties[role_names[name]+"Role"] = PackProperty(""); |
577 | + } |
578 | + } |
579 | + } |
580 | + |
581 | + QRect rect = parent_view_->visualRect(index_); |
582 | + QRect global_rect( |
583 | + parent_view_->viewport()->mapToGlobal(rect.topLeft()), |
584 | + rect.size()); |
585 | + QRect viewport_contents = parent_view_->viewport()->contentsRect(); |
586 | + properties["onScreen"] = PackProperty(viewport_contents.contains(rect)); |
587 | + properties["globalRect"] = PackProperty(global_rect); |
588 | + |
589 | + return properties; |
590 | +} |
591 | + |
592 | +xpathselect::Node::Ptr QModelIndexNode::GetParent() const |
593 | +{ |
594 | + return parent_; |
595 | +} |
596 | + |
597 | +std::string QModelIndexNode::GetName() const |
598 | +{ |
599 | + return "QModelIndex"; |
600 | +} |
601 | + |
602 | +std::string QModelIndexNode::GetPath() const |
603 | +{ |
604 | + return full_path_; |
605 | +} |
606 | + |
607 | +int32_t QModelIndexNode::GetId() const |
608 | +{ |
609 | + // ahha, the rub. Need to use a hash here, but we might lose precision? |
610 | + return qHash(index_); |
611 | +} |
612 | + |
613 | +bool QModelIndexNode::MatchStringProperty(const std::string& name, const std::string& value) const |
614 | +{ |
615 | + QVariantMap properties = GetProperties(); |
616 | + QString qname = QString::fromStdString(name); |
617 | + QVariant qvalue = QVariant(QString::fromStdString(value)); |
618 | + return MatchProperty(properties, qname, qvalue); |
619 | +} |
620 | + |
621 | +bool QModelIndexNode::MatchIntegerProperty(const std::string& name, int32_t value) const |
622 | +{ |
623 | + if (name == "id") |
624 | + return value == GetId(); |
625 | + |
626 | + QVariantMap properties = GetProperties(); |
627 | + QString qname = QString::fromStdString(name); |
628 | + QVariant qvalue = QVariant(value); |
629 | + return MatchProperty(properties, qname, qvalue); |
630 | +} |
631 | + |
632 | +bool QModelIndexNode::MatchBooleanProperty(const std::string& name, bool value) const |
633 | +{ |
634 | + QVariantMap properties = GetProperties(); |
635 | + QString qname = QString::fromStdString(name); |
636 | + QVariant qvalue = QVariant(value); |
637 | + return MatchProperty(properties, qname, qvalue); |
638 | +} |
639 | + |
640 | +xpathselect::NodeVector QModelIndexNode::Children() const |
641 | +{ |
642 | + // Doesn't have any children. |
643 | + xpathselect::NodeVector children; |
644 | + return children; |
645 | +} |
646 | + |
647 | +// QTableWidgetItemNode |
648 | +QTableWidgetItemNode::QTableWidgetItemNode(QTableWidgetItem *item, DBusNode::Ptr parent) |
649 | + : item_(item) |
650 | + , parent_(parent) |
651 | +{ |
652 | + std::string parent_path = parent ? parent->GetPath() : ""; |
653 | + full_path_ = parent_path + "/" + GetName(); |
654 | +} |
655 | + |
656 | +QTableWidgetItemNode::QTableWidgetItemNode(QTableWidgetItem *item) |
657 | + : item_(item) |
658 | +{ |
659 | + full_path_ = "/" + GetName(); |
660 | +} |
661 | + |
662 | +NodeIntrospectionData QTableWidgetItemNode::GetIntrospectionData() const |
663 | +{ |
664 | + NodeIntrospectionData data; |
665 | + data.object_path = QString::fromStdString(GetPath()); |
666 | + data.state = GetProperties(); |
667 | + data.state["id"] = PackProperty(GetId()); |
668 | + return data; |
669 | +} |
670 | + |
671 | +QVariantMap QTableWidgetItemNode::GetProperties() const |
672 | +{ |
673 | + QVariantMap properties; |
674 | + |
675 | + QTableWidget* parent = item_->tableWidget(); |
676 | + QRect cellrect = parent->visualItemRect(item_); |
677 | + QRect r = QRect(parent->mapToGlobal(cellrect.topLeft()), cellrect.size()); |
678 | + properties["globalRect"] = PackProperty(r); |
679 | + |
680 | + properties["text"] = SafePackProperty(PackProperty(item_->text())); |
681 | + properties["toolTip"] = SafePackProperty(PackProperty(item_->toolTip())); |
682 | + // safePackProperty(item_->icon().isNull() ? PackProperty("") : PackProperty(item_->icon())); |
683 | + properties["icon"] = SafePackProperty(PackProperty(item_->icon())); |
684 | + properties["whatsThis"] = SafePackProperty(PackProperty(item_->whatsThis())); |
685 | + properties["row"] = SafePackProperty(PackProperty(item_->row())); |
686 | + properties["isSelected"] = SafePackProperty(PackProperty(item_->isSelected())); |
687 | + properties["column"] = SafePackProperty(PackProperty(item_->column())); |
688 | + |
689 | + return properties; |
690 | +} |
691 | + |
692 | +xpathselect::Node::Ptr QTableWidgetItemNode::GetParent() const |
693 | +{ |
694 | + return parent_; |
695 | +} |
696 | + |
697 | +std::string QTableWidgetItemNode::GetName() const |
698 | +{ |
699 | + return "QTableWidgetItem"; |
700 | +} |
701 | + |
702 | +std::string QTableWidgetItemNode::GetPath() const |
703 | +{ |
704 | + return full_path_; |
705 | +} |
706 | + |
707 | +int32_t QTableWidgetItemNode::GetId() const |
708 | +{ |
709 | + return static_cast<int32_t>(reinterpret_cast<qptrdiff>(item_)); |
710 | +} |
711 | + |
712 | +bool QTableWidgetItemNode::MatchStringProperty(const std::string& name, const std::string& value) const |
713 | +{ |
714 | + QVariantMap properties = GetProperties(); |
715 | + QString qname = QString::fromStdString(name); |
716 | + QVariant qvalue = QVariant(QString::fromStdString(value)); |
717 | + return MatchProperty(properties, qname, qvalue); |
718 | +} |
719 | + |
720 | +bool QTableWidgetItemNode::MatchIntegerProperty(const std::string& name, int32_t value) const |
721 | +{ |
722 | + if (name == "id") |
723 | + return value == GetId(); |
724 | + |
725 | + QVariantMap properties = GetProperties(); |
726 | + QString qname = QString::fromStdString(name); |
727 | + QVariant qvalue = QVariant(value); |
728 | + return MatchProperty(properties, qname, qvalue); |
729 | +} |
730 | + |
731 | +bool QTableWidgetItemNode::MatchBooleanProperty(const std::string& name, bool value) const |
732 | +{ |
733 | + QVariantMap properties = GetProperties(); |
734 | + QString qname = QString::fromStdString(name); |
735 | + QVariant qvalue = QVariant(value); |
736 | + return MatchProperty(properties, qname, qvalue); |
737 | +} |
738 | + |
739 | +xpathselect::NodeVector QTableWidgetItemNode::Children() const |
740 | +{ |
741 | + // Doesn't have any children. |
742 | + xpathselect::NodeVector children; |
743 | + return children; |
744 | +} |
745 | + |
746 | +// QTreeWidgetItemNode |
747 | +QTreeWidgetItemNode::QTreeWidgetItemNode(QTreeWidgetItem *item, DBusNode::Ptr parent) |
748 | + : item_(item) |
749 | + , parent_(parent) |
750 | +{ |
751 | + std::string parent_path = parent ? parent->GetPath() : ""; |
752 | + full_path_ = parent_path + "/" + GetName(); |
753 | +} |
754 | + |
755 | +QTreeWidgetItemNode::QTreeWidgetItemNode(QTreeWidgetItem *item) |
756 | + : item_(item) |
757 | +{ |
758 | + full_path_ = "/" + GetName(); |
759 | +} |
760 | + |
761 | +NodeIntrospectionData QTreeWidgetItemNode::GetIntrospectionData() const |
762 | +{ |
763 | + NodeIntrospectionData data; |
764 | + data.object_path = QString::fromStdString(GetPath()); |
765 | + data.state = GetProperties(); |
766 | + data.state["id"] = PackProperty(GetId()); |
767 | + return data; |
768 | +} |
769 | + |
770 | +QVariantMap QTreeWidgetItemNode::GetProperties() const |
771 | +{ |
772 | + QVariantMap properties; |
773 | + QTreeWidget* parent = item_->treeWidget(); |
774 | + QRect cellrect = parent->visualItemRect(item_); |
775 | + QRect r = QRect(parent->viewport()->mapToGlobal(cellrect.topLeft()), cellrect.size()); |
776 | + properties["globalRect"] = PackProperty(r); |
777 | + |
778 | + properties["text"] = SafePackProperty(item_->text(0)); |
779 | + properties["columns"] = SafePackProperty(item_->columnCount()); |
780 | + properties["checkState"] = SafePackProperty(item_->checkState(0)); |
781 | + |
782 | + properties["isDisabled"] = SafePackProperty(item_->isDisabled()); |
783 | + properties["isExpanded"] = SafePackProperty(item_->isExpanded()); |
784 | + properties["isFirstColumnSpanned"] = SafePackProperty(item_->isFirstColumnSpanned()); |
785 | + properties["isHidden"] = SafePackProperty(item_->isHidden()); |
786 | + properties["isSelected"] = SafePackProperty(item_->isSelected()); |
787 | + |
788 | + return properties; |
789 | +} |
790 | + |
791 | +xpathselect::Node::Ptr QTreeWidgetItemNode::GetParent() const |
792 | +{ |
793 | + return parent_; |
794 | +} |
795 | + |
796 | +std::string QTreeWidgetItemNode::GetName() const |
797 | +{ |
798 | + return "QTreeWidgetItem"; |
799 | +} |
800 | + |
801 | +std::string QTreeWidgetItemNode::GetPath() const |
802 | +{ |
803 | + return full_path_; |
804 | +} |
805 | + |
806 | +int32_t QTreeWidgetItemNode::GetId() const |
807 | +{ |
808 | + return static_cast<int32_t>(reinterpret_cast<qptrdiff>(item_)); |
809 | +} |
810 | + |
811 | +bool QTreeWidgetItemNode::MatchStringProperty(const std::string& name, const std::string& value) const |
812 | +{ |
813 | + QVariantMap properties = GetProperties(); |
814 | + QString qname = QString::fromStdString(name); |
815 | + QVariant qvalue = QVariant(QString::fromStdString(value)); |
816 | + return MatchProperty(properties, qname, qvalue); |
817 | +} |
818 | + |
819 | +bool QTreeWidgetItemNode::MatchIntegerProperty(const std::string& name, int32_t value) const |
820 | +{ |
821 | + if (name == "id") |
822 | + return value == GetId(); |
823 | + |
824 | + QVariantMap properties = GetProperties(); |
825 | + QString qname = QString::fromStdString(name); |
826 | + QVariant qvalue = QVariant(value); |
827 | + return MatchProperty(properties, qname, qvalue); |
828 | +} |
829 | + |
830 | +bool QTreeWidgetItemNode::MatchBooleanProperty(const std::string& name, bool value) const |
831 | +{ |
832 | + QVariantMap properties = GetProperties(); |
833 | + QString qname = QString::fromStdString(name); |
834 | + QVariant qvalue = QVariant(value); |
835 | + return MatchProperty(properties, qname, qvalue); |
836 | +} |
837 | + |
838 | +xpathselect::NodeVector QTreeWidgetItemNode::Children() const |
839 | +{ |
840 | + xpathselect::NodeVector children; |
841 | + |
842 | + for(int i=0; i < item_->childCount(); ++i) { |
843 | + children.push_back( |
844 | + std::make_shared<QTreeWidgetItemNode>(item_->child(i),shared_from_this()) |
845 | + ); |
846 | + } |
847 | + |
848 | + return children; |
849 | } |
850 | |
851 | === modified file 'driver/qtnode.h' |
852 | --- driver/qtnode.h 2014-03-12 13:26:27 +0000 |
853 | +++ driver/qtnode.h 2014-06-20 04:04:19 +0000 |
854 | @@ -6,6 +6,13 @@ |
855 | #include <QDBusArgument> |
856 | #include <xpathselect/node.h> |
857 | |
858 | +#include <QModelIndex> |
859 | + |
860 | +class QAbstractItemView; |
861 | +class QTableWidgetItem; |
862 | +class QTreeView; |
863 | +class QTreeWidgetItem; |
864 | + |
865 | /// A simple data structure representing the state of a single node: |
866 | struct NodeIntrospectionData |
867 | { |
868 | @@ -19,25 +26,38 @@ |
869 | QDBusArgument &operator<<(QDBusArgument &argument, const NodeIntrospectionData &node_data); |
870 | const QDBusArgument &operator>>(const QDBusArgument &argument, NodeIntrospectionData &node_data); |
871 | |
872 | -/// Base class for all Qt-based object nodes. |
873 | +// Interface for Introspecting an object to query it's details. |
874 | +class DBusNode : public xpathselect::Node |
875 | +{ |
876 | +public: |
877 | + typedef std::shared_ptr<const DBusNode> Ptr; |
878 | + |
879 | + DBusNode() {} |
880 | + virtual ~DBusNode() {} |
881 | + |
882 | + virtual NodeIntrospectionData GetIntrospectionData() const=0; |
883 | +}; |
884 | + |
885 | +/// Specialist class for all QObject object nodes. |
886 | +/// This will cover a majority of what we use and we will only need to break |
887 | +/// out to specilist classes for a couple of minor (i.e. QModelIndex) |
888 | /// |
889 | -/// QtNode wraps a single QObject pointer. It derives from xpathselect::Node and, |
890 | -/// like that class, is designed to be allocated on the heap and stored in a |
891 | -/// std::shared_ptr. |
892 | -class QtNode: public xpathselect::Node, public std::enable_shared_from_this<QtNode> |
893 | +/// QObjectNode wraps a single QObject pointer. It derives from |
894 | +/// xpathselect::Node (DBusNode) and, like that class, is designed to be |
895 | +/// allocated on the heap and stored in a std::shared_ptr. |
896 | +class QObjectNode : public DBusNode, public std::enable_shared_from_this<QObjectNode> |
897 | { |
898 | public: |
899 | - typedef std::shared_ptr<const QtNode> Ptr; |
900 | - |
901 | - QtNode(QObject* object, Ptr parent); |
902 | - explicit QtNode(QObject* object); |
903 | + QObjectNode(QObject* object, DBusNode::Ptr parent); |
904 | + explicit QObjectNode(QObject* object); |
905 | |
906 | QObject* getWrappedObject() const; |
907 | + |
908 | + // DBusNode |
909 | + virtual NodeIntrospectionData GetIntrospectionData() const; |
910 | + |
911 | + // xpathselect::Node |
912 | xpathselect::Node::Ptr GetParent() const; |
913 | - |
914 | - virtual NodeIntrospectionData GetIntrospectionData() const; |
915 | - |
916 | - |
917 | virtual std::string GetName() const; |
918 | virtual std::string GetPath() const; |
919 | virtual int32_t GetId() const; |
920 | @@ -45,10 +65,93 @@ |
921 | virtual bool MatchIntegerProperty(const std::string& name, int32_t value) const; |
922 | virtual bool MatchBooleanProperty(const std::string& name, bool value) const; |
923 | virtual xpathselect::NodeVector Children() const; |
924 | + |
925 | private: |
926 | QObject *object_; |
927 | std::string full_path_; |
928 | - Ptr parent_; |
929 | + DBusNode::Ptr parent_; |
930 | +}; |
931 | + |
932 | +class QModelIndexNode : public DBusNode, public std::enable_shared_from_this<QModelIndexNode> |
933 | +{ |
934 | +public: |
935 | + QModelIndexNode(QModelIndex index, QAbstractItemView* parent_view, DBusNode::Ptr parent); |
936 | + explicit QModelIndexNode(QModelIndex index, QAbstractItemView* parent_view); |
937 | + |
938 | + // DBusNode |
939 | + virtual NodeIntrospectionData GetIntrospectionData() const; |
940 | + |
941 | + // xpathselect::Node |
942 | + xpathselect::Node::Ptr GetParent() const; |
943 | + virtual std::string GetName() const; |
944 | + virtual std::string GetPath() const; |
945 | + virtual int32_t GetId() const; |
946 | + virtual bool MatchStringProperty(const std::string& name, const std::string& value) const; |
947 | + virtual bool MatchIntegerProperty(const std::string& name, int32_t value) const; |
948 | + virtual bool MatchBooleanProperty(const std::string& name, bool value) const; |
949 | + virtual xpathselect::NodeVector Children() const; |
950 | + |
951 | +private: |
952 | + QVariantMap GetProperties() const; |
953 | + |
954 | + QModelIndex index_; |
955 | + QAbstractItemView* parent_view_; |
956 | + std::string full_path_; |
957 | + DBusNode::Ptr parent_; |
958 | +}; |
959 | + |
960 | +class QTableWidgetItemNode : public DBusNode, public std::enable_shared_from_this<QTableWidgetItemNode> |
961 | +{ |
962 | +public: |
963 | + QTableWidgetItemNode(QTableWidgetItem *item, DBusNode::Ptr parent); |
964 | + explicit QTableWidgetItemNode(QTableWidgetItem *item); |
965 | + |
966 | + // DBusNode |
967 | + virtual NodeIntrospectionData GetIntrospectionData() const; |
968 | + |
969 | + // xpathselect::Node |
970 | + xpathselect::Node::Ptr GetParent() const; |
971 | + virtual std::string GetName() const; |
972 | + virtual std::string GetPath() const; |
973 | + virtual int32_t GetId() const; |
974 | + virtual bool MatchStringProperty(const std::string& name, const std::string& value) const; |
975 | + virtual bool MatchIntegerProperty(const std::string& name, int32_t value) const; |
976 | + virtual bool MatchBooleanProperty(const std::string& name, bool value) const; |
977 | + virtual xpathselect::NodeVector Children() const; |
978 | + |
979 | +private: |
980 | + QVariantMap GetProperties() const; |
981 | + |
982 | + QTableWidgetItem *item_; |
983 | + std::string full_path_; |
984 | + DBusNode::Ptr parent_; |
985 | +}; |
986 | + |
987 | +class QTreeWidgetItemNode : public DBusNode, public std::enable_shared_from_this<QTreeWidgetItemNode> |
988 | +{ |
989 | +public: |
990 | + QTreeWidgetItemNode(QTreeWidgetItem *item, DBusNode::Ptr parent); |
991 | + explicit QTreeWidgetItemNode(QTreeWidgetItem *item); |
992 | + |
993 | + // DBusNode |
994 | + virtual NodeIntrospectionData GetIntrospectionData() const; |
995 | + |
996 | + // xpathselect::Node |
997 | + xpathselect::Node::Ptr GetParent() const; |
998 | + virtual std::string GetName() const; |
999 | + virtual std::string GetPath() const; |
1000 | + virtual int32_t GetId() const; |
1001 | + virtual bool MatchStringProperty(const std::string& name, const std::string& value) const; |
1002 | + virtual bool MatchIntegerProperty(const std::string& name, int32_t value) const; |
1003 | + virtual bool MatchBooleanProperty(const std::string& name, bool value) const; |
1004 | + virtual xpathselect::NodeVector Children() const; |
1005 | + |
1006 | +private: |
1007 | + QVariantMap GetProperties() const; |
1008 | + |
1009 | + QTreeWidgetItem *item_; |
1010 | + std::string full_path_; |
1011 | + DBusNode::Ptr parent_; |
1012 | }; |
1013 | |
1014 | #endif // QTNODE_H |
1015 | |
1016 | === modified file 'driver/rootnode.cpp' |
1017 | --- driver/rootnode.cpp 2013-09-03 04:45:05 +0000 |
1018 | +++ driver/rootnode.cpp 2014-06-20 04:04:19 +0000 |
1019 | @@ -7,7 +7,7 @@ |
1020 | #include <QDebug> |
1021 | |
1022 | RootNode::RootNode(QCoreApplication* application) |
1023 | - : QtNode(application) |
1024 | + : QObjectNode(application) |
1025 | , application_(application) |
1026 | { |
1027 | } |
1028 | @@ -49,6 +49,6 @@ |
1029 | { |
1030 | xpathselect::NodeVector children; |
1031 | foreach(QObject* child, children_) |
1032 | - children.push_back(std::make_shared<QtNode>(child, shared_from_this())); |
1033 | + children.push_back(std::make_shared<QObjectNode>(child, shared_from_this())); |
1034 | return children; |
1035 | } |
1036 | |
1037 | === modified file 'driver/rootnode.h' |
1038 | --- driver/rootnode.h 2013-09-03 04:45:05 +0000 |
1039 | +++ driver/rootnode.h 2014-06-20 04:04:19 +0000 |
1040 | @@ -8,7 +8,7 @@ |
1041 | class QObject; |
1042 | |
1043 | |
1044 | -class RootNode: public QtNode |
1045 | +class RootNode: public QObjectNode |
1046 | { |
1047 | public: |
1048 | RootNode(QCoreApplication* application); |
1049 | |
1050 | === modified file 'tests/unittests/tst_introspection.cpp' |
1051 | --- tests/unittests/tst_introspection.cpp 2014-03-12 13:26:27 +0000 |
1052 | +++ tests/unittests/tst_introspection.cpp 2014-06-20 04:04:19 +0000 |
1053 | @@ -503,7 +503,7 @@ |
1054 | |
1055 | void tst_Introspection::test_property_matching() |
1056 | { |
1057 | - QtNode n(m_object); |
1058 | + QObjectNode n(m_object); |
1059 | |
1060 | QVERIFY(n.MatchStringProperty("dynamicStringProperty", "testValue") == true); |
1061 | QVERIFY(n.MatchStringProperty("dynamicTestProperty", "testValue") == true); |
Generally looks good, but the diff is too large to really review properly - a few fixes needed.