1 #include "ModelDataExtractor.hxx"
2
3 #include <QAbstractItemModel>
4 #include <QDebug>
5
ModelDataExtractor(QObject * parent)6 ModelDataExtractor::ModelDataExtractor(QObject *parent) : QObject(parent)
7 {
8
9 }
10
data() const11 QVariant ModelDataExtractor::data() const
12 {
13 if (m_model) {
14 QModelIndex m = m_model->index(m_index, 0);
15 if (!m.isValid())
16 return {};
17
18 int role = Qt::DisplayRole;
19 if (!m_role.isEmpty()) {
20 const auto& names = m_model->roleNames();
21 role = names.key(m_role.toUtf8(), Qt::DisplayRole);
22 }
23
24 return m_model->data(m, role);
25 }
26
27 if (!m_stringsModel.empty()) {
28 if ((m_index < 0) || (m_index >= m_stringsModel.size()))
29 return {};
30
31 return m_stringsModel.at(m_index);
32 }
33
34 if (m_rawModel.isArray()) {
35 quint32 uIndex = static_cast<quint32>(m_index);
36 auto v = m_rawModel.property(uIndex);
37 if (v.isQObject()) {
38 // handle the QList<QObject*> case
39 auto obj = v.toQObject();
40 return obj->property(m_role.toUtf8().constData());
41 }
42
43 return m_rawModel.property(uIndex).toVariant();
44 }
45
46 if (!m_rawModel.isUndefined() && !m_rawModel.isNull()) {
47 qWarning() << "Unable to convert model data:" << m_rawModel.toString();
48 }
49
50 return {};
51 }
52
clear()53 void ModelDataExtractor::clear()
54 {
55 if (m_model) {
56 // disconnect from everything
57 disconnect(m_model, nullptr, this, nullptr);
58 m_model = nullptr;
59 }
60
61 }
62
setModel(QJSValue raw)63 void ModelDataExtractor::setModel(QJSValue raw)
64 {
65 if (m_rawModel.strictlyEquals(raw))
66 return;
67
68 clear();
69 m_rawModel = raw;
70
71 if (raw.isQObject()) {
72 m_model = qobject_cast<QAbstractItemModel*>(raw.toQObject());
73 if (m_model) {
74 connect(m_model, &QAbstractItemModel::modelReset,
75 this, &ModelDataExtractor::dataChanged);
76 connect(m_model, &QAbstractItemModel::dataChanged,
77 this, &ModelDataExtractor::onDataChanged);
78
79 // ToDo: handle rows added / removed
80 } else {
81 qWarning() << "object but not a QAIM" << raw.toQObject();
82 }
83 } else if (raw.isArray()) {
84
85 } else if (raw.isVariant() || raw.isObject()) {
86 // special case the QStringList case
87
88 // for reasons I don't understand yet, QStringList returned as a
89 // property value to JS, does not show up as a variant-in-JS-Value above
90 // (so ::isVariant returns false), but conversion to a variant
91 // works. Hence the 'raw.isObject' above
92
93 const auto var = raw.toVariant();
94 if (var.type() == QVariant::StringList) {
95 m_stringsModel = var.toStringList();
96 } else {
97 qWarning() << Q_FUNC_INFO << "variant but not a QStringList" << var;
98 }
99 }
100
101 emit modelChanged();
102 emit dataChanged();
103 }
104
setIndex(int index)105 void ModelDataExtractor::setIndex(int index)
106 {
107 if (m_index == index)
108 return;
109
110 m_index = index;
111 emit indexChanged(m_index);
112 emit dataChanged();
113 }
114
setRole(QString role)115 void ModelDataExtractor::setRole(QString role)
116 {
117 if (m_role == role)
118 return;
119
120 m_role = role;
121 emit roleChanged(m_role);
122 emit dataChanged();
123 }
124
onDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)125 void ModelDataExtractor::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
126 {
127 if ((topLeft.row() >= m_index) && (bottomRight.row() <= m_index)) {
128 emit dataChanged();
129 }
130 }
131