Merge lp:~veebers/autopilot-qt/enable-datamodel-elements into lp:autopilot-qt

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
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, QTableWidgetItemNode and QTreeWidgetItemNode with room for more.

To post a comment you must log in.
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

Generally looks good, but the diff is too large to really review properly - a few fixes needed.

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);

Subscribers

People subscribed via source and target branches