18
18
#include <QDBusArgument>
20
#include <QAbstractItemView>
21
#include <QAbstractProxyModel>
22
#include <QTableWidget>
24
#include <QTreeWidget>
27
const QByteArray AP_ID_NAME("_autopilot_id");
29
void CollectSpecialChildren(QObject* object, xpathselect::NodeVector& children, DBusNode::Ptr parent);
31
void GetDataElementChildren(QTableWidget* table, xpathselect::NodeVector& children, DBusNode::Ptr parent);
32
void GetDataElementChildren(QTreeView* tree_view, xpathselect::NodeVector& children, DBusNode::Ptr parent);
33
void GetDataElementChildren(QTreeWidget* tree_widget, xpathselect::NodeVector& children, DBusNode::Ptr parent);
34
void GetDataElementChildren(QListView* list_view, xpathselect::NodeVector& children, DBusNode::Ptr parent);
36
void CollectAllIndices(QModelIndex index, QAbstractItemModel *model, QModelIndexList &collection);
37
QVariant SafePackProperty(QVariant const& prop);
39
bool MatchProperty(QVariantMap const& packed_properties, std::string const& name, QVariant value);
41
// Produce an id suitable for xpathselects' GetId
42
int32_t calculate_ap_id(quint64 big_id)
44
int32_t high = static_cast<int32_t>(big_id >> 32);
45
int32_t low = static_cast<int32_t>(big_id);
20
49
// Marshall the NodeIntrospectionData data into a D-Bus argument
21
QDBusArgument &operator<<(QDBusArgument &argument, const NodeIntrospectionData &node_data)
50
QDBusArgument &operator<<(QDBusArgument &argument, NodeIntrospectionData const& node_data)
23
52
argument.beginStructure();
24
53
argument << node_data.object_path << node_data.state;
38
const QByteArray AP_ID_NAME("_autopilot_id");
67
void GetDataElementChildren(QTableWidget *table, xpathselect::NodeVector& children, DBusNode::Ptr parent)
69
QList<QTableWidgetItem *> tablewidgetitems = table->findItems("*", Qt::MatchWildcard|Qt::MatchRecursive);
70
foreach (QTableWidgetItem *item, tablewidgetitems){
72
std::make_shared<QTableWidgetItemNode>(item, parent)
77
void CollectAllIndices(QModelIndex index, QAbstractItemModel *model, QModelIndexList &collection)
79
for(int c=0; c < model->columnCount(index); ++c) {
80
for(int r=0; r < model->rowCount(index); ++r) {
81
QModelIndex new_index = model->index(r, c, index);
82
collection.push_back(new_index);
83
if(new_index.isValid() && qHash(new_index) != qHash(index)) {
84
CollectAllIndices(new_index, model, collection);
90
// Pack property, but return a default blank if the packed property is invalid.
91
QVariant SafePackProperty(QVariant const& prop)
93
static QVariant blank_default = PackProperty("");
95
QVariant property_attempt = PackProperty(prop);
96
if(property_attempt.isValid())
97
return property_attempt;
102
bool MatchProperty(QVariantMap const& packed_properties, std::string const& name, QVariant value)
104
QString qname = QString::fromStdString(name);
105
if (! packed_properties.contains(qname))
108
// Because the properties are packed, we need the value, not the type.
109
QVariant object_value = qvariant_cast<QVariantList>(packed_properties[qname]).at(1);
110
if (value.canConvert(object_value.type()))
112
value.convert(object_value.type());
113
return value == object_value;
119
void GetDataElementChildren(QTreeView* tree_view, xpathselect::NodeVector& children, DBusNode::Ptr parent)
121
QAbstractItemModel* abstract_model = tree_view->model();
124
qDebug() << "Unable to get element children from QTreeView "
125
<< "with objectName '" << tree_view->objectName() << "'. "
126
<< "No model found.";
130
QModelIndexList all_indices;
131
for(int c=0; c < abstract_model->columnCount(); ++c) {
132
for(int r=0; r < abstract_model->rowCount(); ++r) {
133
QModelIndex index = abstract_model->index(r, c);
134
all_indices.push_back(index);
135
CollectAllIndices(index, abstract_model, all_indices);
139
foreach(QModelIndex index, all_indices)
144
std::make_shared<QModelIndexNode>(
153
void GetDataElementChildren(QTreeWidget* tree_widget, xpathselect::NodeVector& children, DBusNode::Ptr parent)
155
for(int i=0; i < tree_widget->topLevelItemCount(); ++i) {
157
std::make_shared<QTreeWidgetItemNode>(
158
tree_widget->topLevelItem(i),
164
void GetDataElementChildren(QListView* list_view, xpathselect::NodeVector& children, DBusNode::Ptr parent)
166
QAbstractItemModel* abstract_model = list_view->model();
168
if(! abstract_model) {
169
qDebug() << "Unable to get element children from QListView "
170
<< "with objectName '" << list_view->objectName() << "'. "
171
<< "No model found.";
175
QModelIndexList all_indices;
176
QModelIndex root_index = list_view->rootIndex();
177
if(root_index.isValid()) {
178
// The root item is the parent item to the view's toplevel items
179
CollectAllIndices(root_index, abstract_model, all_indices);
182
for(int c=0; c < abstract_model->columnCount(); ++c) {
183
for(int r=0; r < abstract_model->rowCount(); ++r) {
184
QModelIndex index = abstract_model->index(r, c);
185
all_indices.push_back(index);
186
CollectAllIndices(index, abstract_model, all_indices);
191
foreach(QModelIndex index, all_indices) {
195
std::make_shared<QModelIndexNode>(
40
204
QObjectNode::QObjectNode(QObject *obj, DBusNode::Ptr parent)
97
260
return qvariant_cast<int32_t>(object_->property(AP_ID_NAME));
100
bool QObjectNode::MatchStringProperty(const std::string& name, const std::string& value) const
263
bool QObjectNode::MatchStringProperty(std::string const& name, std::string const& value) const
102
QVariantMap properties = GetNodeProperties(object_);
104
QString qname = QString::fromStdString(name);
105
if (! properties.contains(qname))
108
QVariant object_value = qvariant_cast<QVariantList>(properties[qname]).at(1);
109
QVariant check_value(QString::fromStdString(value));
110
if (check_value.canConvert(object_value.type()))
112
check_value.convert(object_value.type());
113
return check_value == object_value;
265
return MatchProperty(GetNodeProperties(object_), name, QString::fromStdString(value));
119
bool QObjectNode::MatchIntegerProperty(const std::string& name, int32_t value) const
268
bool QObjectNode::MatchIntegerProperty(std::string const& name, int32_t value) const
121
270
if (name == "id")
122
271
return value == GetId();
124
QVariantMap properties = GetNodeProperties(object_);
126
QString qname = QString::fromStdString(name);
127
if (! properties.contains(qname))
130
QVariant object_value = qvariant_cast<QVariantList>(properties[qname]).at(1);
131
QVariant check_value(value);
132
if (check_value.canConvert(object_value.type()))
134
check_value.convert(object_value.type());
135
return check_value == object_value;
141
bool QObjectNode::MatchBooleanProperty(const std::string& name, bool value) const
143
QVariantMap properties = GetNodeProperties(object_);
145
QString qname = QString::fromStdString(name);
146
if (! properties.contains(qname))
149
QVariant object_value = qvariant_cast<QVariantList>(properties[qname]).at(1);
150
QVariant check_value(value);
152
if (check_value.canConvert(object_value.type()))
154
check_value.convert(object_value.type());
155
return check_value == object_value;
273
return MatchProperty(GetNodeProperties(object_), name, value);
276
bool QObjectNode::MatchBooleanProperty(std::string const& name, bool value) const
278
return MatchProperty(GetNodeProperties(object_), name, value);
282
bool AttemptGetSpecialChildren(QObject* object, xpathselect::NodeVector& children, DBusNode::Ptr parent)
284
auto className = T::staticMetaObject.className();
285
if(object->inherits(className))
287
T* table = qobject_cast<T *>(object);
289
GetDataElementChildren(table, children, parent);
292
qDebug() << "Casting object (with objectName: " << object->objectName() << ") "
293
<< "to " << className
294
<< "failed. Unable to retrieve children.";
302
void CollectSpecialChildren(QObject* object, xpathselect::NodeVector& children, DBusNode::Ptr parent)
304
// Need to make sure to make these checks in the correct order.
305
// i.e. Because QTreeWidget inherits from QTreeView do it first otherwise
306
// we would never reach the specific QTreeWidget code.
307
AttemptGetSpecialChildren<QTableWidget>(object, children, parent)
308
|| AttemptGetSpecialChildren<QTreeWidget>(object, children, parent)
309
|| AttemptGetSpecialChildren<QTreeView>(object, children, parent)
310
|| AttemptGetSpecialChildren<QListView>(object, children, parent);
161
313
xpathselect::NodeVector QObjectNode::Children() const
163
315
xpathselect::NodeVector children;
317
CollectSpecialChildren(object_, children, shared_from_this());
165
319
#ifdef QT5_SUPPORT
166
320
// Qt5's hierarchy for QML has changed a bit:
167
321
// - On top there's a QQuickView which holds all the QQuick items
378
QModelIndexNode::QModelIndexNode(QModelIndex index, QAbstractItemView* parent_view, DBusNode::Ptr parent)
380
, parent_view_(parent_view)
383
std::string parent_path = parent ? parent->GetPath() : "";
384
full_path_ = parent_path + "/" + GetName();
387
NodeIntrospectionData QModelIndexNode::GetIntrospectionData() const
389
NodeIntrospectionData data;
390
data.object_path = QString::fromStdString(GetPath());
391
data.state = GetProperties();
392
data.state["id"] = PackProperty(GetId());
396
QVariantMap QModelIndexNode::GetProperties() const
398
QVariantMap properties;
399
const QAbstractItemModel* model = index_.model();
402
// Make an attempt to store the 'text' of a node to be user friendly-ish.
403
properties["text"] = SafePackProperty(model->data(index_));
405
// Include any Role data (mung the role name with added "Role")
406
const QHash<int, QByteArray> role_names = model->roleNames();
407
QMap<int, QVariant> item_data = model->itemData(index_);
408
foreach(int name, role_names.keys())
410
if(item_data.contains(name)) {
411
properties[role_names[name]+"Role"] = SafePackProperty(item_data[name]);
414
properties[role_names[name]+"Role"] = PackProperty("");
419
QRect rect = parent_view_->visualRect(index_);
421
parent_view_->viewport()->mapToGlobal(rect.topLeft()),
423
QRect viewport_contents = parent_view_->viewport()->contentsRect();
424
properties["onScreen"] = PackProperty(viewport_contents.contains(rect));
425
properties["globalRect"] = PackProperty(global_rect);
430
xpathselect::Node::Ptr QModelIndexNode::GetParent() const
435
std::string QModelIndexNode::GetName() const
437
return "QModelIndex";
440
std::string QModelIndexNode::GetPath() const
445
int32_t QModelIndexNode::GetId() const
447
return calculate_ap_id(static_cast<quint64>(qHash(index_)));
450
bool QModelIndexNode::MatchStringProperty(std::string const& name, std::string const& value) const
452
return MatchProperty(GetProperties(), name, QString::fromStdString(value));
455
bool QModelIndexNode::MatchIntegerProperty(std::string const& name, int32_t value) const
458
return value == GetId();
460
return MatchProperty(GetProperties(), name, value);
463
bool QModelIndexNode::MatchBooleanProperty(std::string const& name, bool value) const
465
return MatchProperty(GetProperties(), name, value);
468
xpathselect::NodeVector QModelIndexNode::Children() const
470
// Doesn't have any children.
471
xpathselect::NodeVector children;
475
// QTableWidgetItemNode
476
QTableWidgetItemNode::QTableWidgetItemNode(QTableWidgetItem *item, DBusNode::Ptr parent)
480
std::string parent_path = parent ? parent->GetPath() : "";
481
full_path_ = parent_path + "/" + GetName();
484
NodeIntrospectionData QTableWidgetItemNode::GetIntrospectionData() const
486
NodeIntrospectionData data;
487
data.object_path = QString::fromStdString(GetPath());
488
data.state = GetProperties();
489
data.state["id"] = PackProperty(GetId());
493
QVariantMap QTableWidgetItemNode::GetProperties() const
495
QVariantMap properties;
497
QTableWidget* parent = item_->tableWidget();
498
QRect cellrect = parent->visualItemRect(item_);
499
QRect r = QRect(parent->mapToGlobal(cellrect.topLeft()), cellrect.size());
500
properties["globalRect"] = PackProperty(r);
502
properties["text"] = SafePackProperty(PackProperty(item_->text()));
503
properties["toolTip"] = SafePackProperty(PackProperty(item_->toolTip()));
504
properties["icon"] = SafePackProperty(PackProperty(item_->icon()));
505
properties["whatsThis"] = SafePackProperty(PackProperty(item_->whatsThis()));
506
properties["row"] = SafePackProperty(PackProperty(item_->row()));
507
properties["isSelected"] = SafePackProperty(PackProperty(item_->isSelected()));
508
properties["column"] = SafePackProperty(PackProperty(item_->column()));
513
xpathselect::Node::Ptr QTableWidgetItemNode::GetParent() const
518
std::string QTableWidgetItemNode::GetName() const
520
return "QTableWidgetItem";
523
std::string QTableWidgetItemNode::GetPath() const
528
int32_t QTableWidgetItemNode::GetId() const
530
return calculate_ap_id(static_cast<quint64>(reinterpret_cast<quintptr>(item_)));
533
bool QTableWidgetItemNode::MatchStringProperty(std::string const& name, std::string const& value) const
535
return MatchProperty(GetProperties(), name, QString::fromStdString(value));
538
bool QTableWidgetItemNode::MatchIntegerProperty(std::string const& name, int32_t value) const
541
return value == GetId();
543
return MatchProperty(GetProperties(), name, value);
546
bool QTableWidgetItemNode::MatchBooleanProperty(std::string const& name, bool value) const
548
return MatchProperty(GetProperties(), name, value);
551
xpathselect::NodeVector QTableWidgetItemNode::Children() const
553
// Doesn't have any children.
554
xpathselect::NodeVector children;
558
// QTreeWidgetItemNode
559
QTreeWidgetItemNode::QTreeWidgetItemNode(QTreeWidgetItem *item, DBusNode::Ptr parent)
563
std::string parent_path = parent ? parent->GetPath() : "";
564
full_path_ = parent_path + "/" + GetName();
567
NodeIntrospectionData QTreeWidgetItemNode::GetIntrospectionData() const
569
NodeIntrospectionData data;
570
data.object_path = QString::fromStdString(GetPath());
571
data.state = GetProperties();
572
data.state["id"] = PackProperty(GetId());
576
QVariantMap QTreeWidgetItemNode::GetProperties() const
578
QVariantMap properties;
579
QTreeWidget* parent = item_->treeWidget();
580
QRect cellrect = parent->visualItemRect(item_);
581
QRect r = QRect(parent->viewport()->mapToGlobal(cellrect.topLeft()), cellrect.size());
582
properties["globalRect"] = PackProperty(r);
584
properties["text"] = SafePackProperty(item_->text(0));
585
properties["columns"] = SafePackProperty(item_->columnCount());
586
properties["checkState"] = SafePackProperty(item_->checkState(0));
588
properties["isDisabled"] = SafePackProperty(item_->isDisabled());
589
properties["isExpanded"] = SafePackProperty(item_->isExpanded());
590
properties["isFirstColumnSpanned"] = SafePackProperty(item_->isFirstColumnSpanned());
591
properties["isHidden"] = SafePackProperty(item_->isHidden());
592
properties["isSelected"] = SafePackProperty(item_->isSelected());
597
xpathselect::Node::Ptr QTreeWidgetItemNode::GetParent() const
602
std::string QTreeWidgetItemNode::GetName() const
604
return "QTreeWidgetItem";
607
std::string QTreeWidgetItemNode::GetPath() const
612
int32_t QTreeWidgetItemNode::GetId() const
614
return calculate_ap_id(static_cast<quint64>(reinterpret_cast<quintptr>(item_)));
617
bool QTreeWidgetItemNode::MatchStringProperty(std::string const& name, std::string const& value) const
619
return MatchProperty(GetProperties(), name, QString::fromStdString(value));
622
bool QTreeWidgetItemNode::MatchIntegerProperty(std::string const& name, int32_t value) const
625
return value == GetId();
627
return MatchProperty(GetProperties(), name, value);
630
bool QTreeWidgetItemNode::MatchBooleanProperty(std::string const& name, bool value) const
632
return MatchProperty(GetProperties(), name, value);
635
xpathselect::NodeVector QTreeWidgetItemNode::Children() const
637
xpathselect::NodeVector children;
639
for(int i=0; i < item_->childCount(); ++i) {
641
std::make_shared<QTreeWidgetItemNode>(item_->child(i),shared_from_this())