source: trunk/examples/xmlpatterns/qobjectxmlmodel/qobjectxmlmodel.cpp@ 275

Last change on this file since 275 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 12.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QVector>
43#include <QtDebug>
44
45#include <QCoreApplication>
46#include <QMetaProperty>
47#include <QXmlQuery>
48#include <QXmlResultItems>
49
50#include "qobjectxmlmodel.h"
51
52QT_BEGIN_NAMESPACE
53
54/*
55<metaObjects>
56 <metaObject className="QObject"/>
57 <metaObject className="QWidget" superClass="QObject">
58 </metaObject>
59 ...
60</metaObjects>
61<QObject objectName="MyWidget" property1="..." property2="..."> <!-- This is root() -->
62 <QObject objectName="MyFOO" property1="..."/>
63 ....
64</QObject>
65*/
66
67QObjectXmlModel::QObjectXmlModel(QObject *const object, const QXmlNamePool &np)
68 : QSimpleXmlNodeModel(np),
69 m_baseURI(QUrl::fromLocalFile(QCoreApplication::applicationFilePath())),
70 m_root(object),
71 m_allMetaObjects(allMetaObjects())
72{
73 Q_ASSERT(m_baseURI.isValid());
74}
75
76//! [5]
77QXmlNodeModelIndex QObjectXmlModel::qObjectSibling(const int pos, const QXmlNodeModelIndex &n) const
78{
79 Q_ASSERT(pos == 1 || pos == -1);
80 Q_ASSERT(asQObject(n));
81
82 const QObject *parent = asQObject(n)->parent();
83 if (parent) {
84 const QList<QObject *> &children = parent->children();
85 const int siblingPos = children.indexOf(asQObject(n)) + pos;
86
87 if (siblingPos >= 0 && siblingPos < children.count())
88 return createIndex(children.at(siblingPos));
89 else
90 return QXmlNodeModelIndex();
91 }
92 else
93 return QXmlNodeModelIndex();
94}
95//! [5]
96
97//! [1]
98QObjectXmlModel::QObjectNodeType QObjectXmlModel::toNodeType(const QXmlNodeModelIndex &n)
99{
100 return QObjectNodeType(n.additionalData() & (15 << 26));
101}
102//! [1]
103
104//! [9]
105QObjectXmlModel::AllMetaObjects QObjectXmlModel::allMetaObjects() const
106{
107 QXmlQuery query(namePool());
108 query.bindVariable("root", root());
109 query.setQuery("declare variable $root external;"
110 "$root/descendant-or-self::QObject");
111 Q_ASSERT(query.isValid());
112
113 QXmlResultItems result;
114 query.evaluateTo(&result);
115 QXmlItem i(result.next());
116
117 AllMetaObjects objects;
118 while (!i.isNull()) {
119 const QMetaObject *moo = asQObject(i.toNodeModelIndex())->metaObject();
120 while (moo) {
121 if (!objects.contains(moo))
122 objects.append(moo);
123 moo = moo->superClass();
124 }
125 i = result.next();
126 }
127
128 Q_ASSERT(!objects.contains(0));
129 return objects;
130}
131//! [9]
132
133QXmlNodeModelIndex QObjectXmlModel::metaObjectSibling(const int pos, const QXmlNodeModelIndex &n) const
134{
135 Q_ASSERT(pos == 1 || pos == -1);
136 Q_ASSERT(!n.isNull());
137
138 const int indexOf = m_allMetaObjects.indexOf(static_cast<const QMetaObject *>(n.internalPointer())) + pos;
139
140 if (indexOf >= 0 && indexOf < m_allMetaObjects.count())
141 return createIndex(const_cast<QMetaObject *>(m_allMetaObjects.at(indexOf)), MetaObject);
142 else
143 return QXmlNodeModelIndex();
144}
145
146//! [2]
147QXmlNodeModelIndex QObjectXmlModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &n) const
148{
149 switch (toNodeType(n))
150 {
151 case IsQObject:
152 {
153 switch (axis)
154 {
155 case Parent:
156 return createIndex(asQObject(n)->parent());
157
158 case FirstChild:
159 {
160 if (!asQObject(n) || asQObject(n)->children().isEmpty())
161 return QXmlNodeModelIndex();
162 else
163 return createIndex(asQObject(n)->children().first());
164 }
165
166 case NextSibling:
167 return qObjectSibling(1, n);
168
169//! [10]
170 case PreviousSibling:
171 {
172 if (asQObject(n) == m_root)
173 return createIndex(qint64(0), MetaObjects);
174 else
175 return qObjectSibling(-1, n);
176 }
177//! [10]
178 }
179 Q_ASSERT(false);
180 }
181
182//! [7]
183 case QObjectClassName:
184 case QObjectProperty:
185 {
186 Q_ASSERT(axis == Parent);
187 return createIndex(asQObject(n));
188 }
189//! [7]
190//! [2]
191//! [3]
192
193//! [11]
194 case MetaObjects:
195 {
196 switch (axis)
197 {
198 case Parent:
199 return QXmlNodeModelIndex();
200 case PreviousSibling:
201 return QXmlNodeModelIndex();
202 case NextSibling:
203 return root();
204 case FirstChild:
205 {
206 return createIndex(const_cast<QMetaObject*>(m_allMetaObjects.first()),MetaObject);
207 }
208 }
209 Q_ASSERT(false);
210 }
211//! [11]
212
213 case MetaObject:
214 {
215 switch (axis)
216 {
217 case FirstChild:
218 return QXmlNodeModelIndex();
219 case Parent:
220 return createIndex(qint64(0), MetaObjects);
221 case PreviousSibling:
222 return metaObjectSibling(-1, n);
223 case NextSibling:
224 return metaObjectSibling(1, n);
225 }
226 }
227
228 case MetaObjectClassName:
229 case MetaObjectSuperClass:
230 {
231 Q_ASSERT(axis == Parent);
232 return createIndex(asQObject(n), MetaObject);
233 }
234//! [3]
235//! [4]
236 }
237
238 Q_ASSERT(false);
239 return QXmlNodeModelIndex();
240}
241//! [4]
242
243//! [6]
244QVector<QXmlNodeModelIndex> QObjectXmlModel::attributes(const QXmlNodeModelIndex& n) const
245{
246 QVector<QXmlNodeModelIndex> result;
247 QObject *const object = asQObject(n);
248
249 switch(toNodeType(n))
250 {
251 case IsQObject:
252 {
253 const QMetaObject *const metaObject = object->metaObject();
254 const int count = metaObject->propertyCount();
255 result.append(createIndex(object, QObjectClassName));
256
257 for (int i = 0; i < count; ++i) {
258 const QMetaProperty qmp(metaObject->property(i));
259 const int ii = metaObject->indexOfProperty(qmp.name());
260 if (i == ii)
261 result.append(createIndex(object, QObjectProperty | i));
262 }
263 return result;
264 }
265//! [6]
266
267 case MetaObject:
268 {
269 result.append(createIndex(object, MetaObjectClassName));
270 result.append(createIndex(object, MetaObjectSuperClass));
271 return result;
272 }
273//! [8]
274 default:
275 return QVector<QXmlNodeModelIndex>();
276 }
277}
278//! [8]
279
280QObject *QObjectXmlModel::asQObject(const QXmlNodeModelIndex &n)
281{
282 return static_cast<QObject *>(n.internalPointer());
283}
284
285bool QObjectXmlModel::isProperty(const QXmlNodeModelIndex n)
286{
287 return n.additionalData() & QObjectProperty;
288}
289
290QUrl QObjectXmlModel::documentUri(const QXmlNodeModelIndex& ) const
291{
292 return m_baseURI;
293}
294
295QXmlNodeModelIndex::NodeKind QObjectXmlModel::kind(const QXmlNodeModelIndex& n) const
296{
297 switch (toNodeType(n))
298 {
299 case IsQObject:
300 case MetaObject:
301 case MetaObjects:
302 return QXmlNodeModelIndex::Element;
303
304 case QObjectProperty:
305 case MetaObjectClassName:
306 case MetaObjectSuperClass:
307 case QObjectClassName:
308 return QXmlNodeModelIndex::Attribute;
309 }
310
311 Q_ASSERT(false);
312 return QXmlNodeModelIndex::Element;
313}
314
315QXmlNodeModelIndex::DocumentOrder QObjectXmlModel::compareOrder(const QXmlNodeModelIndex& , const QXmlNodeModelIndex& ) const
316{
317 return QXmlNodeModelIndex::Follows; // TODO
318}
319
320//! [0]
321QXmlNodeModelIndex QObjectXmlModel::root() const
322{
323 return createIndex(m_root);
324}
325//! [0]
326
327QXmlNodeModelIndex QObjectXmlModel::root(const QXmlNodeModelIndex& n) const
328{
329 QObject *p = asQObject(n);
330 Q_ASSERT(p);
331
332 do {
333 QObject *const candidate = p->parent();
334 if (candidate)
335 p = candidate;
336 else
337 break;
338 }
339 while (true);
340
341 return createIndex(p);
342}
343
344/*!
345 We simply throw all of them into a QList and
346 return an iterator over it.
347 */
348QXmlNodeModelIndex::List QObjectXmlModel::ancestors(const QXmlNodeModelIndex n) const
349{
350 const QObject *p = asQObject(n);
351 Q_ASSERT(p);
352
353 QXmlNodeModelIndex::List result;
354 do {
355 QObject *const candidate = p->parent();
356 if (candidate) {
357 result.append(createIndex(candidate, 0));
358 p = candidate;
359 }
360 else
361 break;
362 }
363 while (true);
364
365 return result;
366}
367
368QMetaProperty QObjectXmlModel::toMetaProperty(const QXmlNodeModelIndex &n)
369{
370 const int propertyOffset = n.additionalData() & (~QObjectProperty);
371 const QObject *const qo = asQObject(n);
372 return qo->metaObject()->property(propertyOffset);
373}
374
375QXmlName QObjectXmlModel::name(const QXmlNodeModelIndex &n) const
376{
377 switch (toNodeType(n))
378 {
379 case IsQObject:
380 return QXmlName(namePool(), QLatin1String("QObject"));
381 case MetaObject:
382 return QXmlName(namePool(), QLatin1String("metaObject"));
383 case QObjectClassName:
384 case MetaObjectClassName:
385 return QXmlName(namePool(), QLatin1String("className"));
386 case QObjectProperty:
387 return QXmlName(namePool(), toMetaProperty(n).name());
388 case MetaObjects:
389 return QXmlName(namePool(), QLatin1String("metaObjects"));
390 case MetaObjectSuperClass:
391 return QXmlName(namePool(), QLatin1String("superClass"));
392 }
393
394 Q_ASSERT(false);
395 return QXmlName();
396}
397
398QVariant QObjectXmlModel::typedValue(const QXmlNodeModelIndex &n) const
399{
400 switch (toNodeType(n))
401 {
402 case QObjectProperty:
403 {
404 const QVariant &candidate = toMetaProperty(n).read(asQObject(n));
405 if (isTypeSupported(candidate.type()))
406 return candidate;
407 else
408 return QVariant();
409 }
410
411 case MetaObjectClassName:
412 return QVariant(static_cast<QMetaObject*>(n.internalPointer())->className());
413
414 case MetaObjectSuperClass:
415 {
416 const QMetaObject *const superClass = static_cast<QMetaObject*>(n.internalPointer())->superClass();
417 if (superClass)
418 return QVariant(superClass->className());
419 else
420 return QVariant();
421 }
422
423 case QObjectClassName:
424 return QVariant(asQObject(n)->metaObject()->className());
425
426 default:
427 return QVariant();
428 }
429}
430
431/*!
432 Returns \c true if QVariants of type \a type can be used
433 in QtXmlPatterns, otherwise \c false.
434 */
435bool QObjectXmlModel::isTypeSupported(QVariant::Type type)
436{
437 /* See data/qatomicvalue.cpp too. */
438 switch (type)
439 {
440 /* Fallthrough all these. */
441 case QVariant::Char:
442 case QVariant::String:
443 case QVariant::Url:
444 case QVariant::Bool:
445 case QVariant::ByteArray:
446 case QVariant::Int:
447 case QVariant::LongLong:
448 case QVariant::ULongLong:
449 case QVariant::Date:
450 case QVariant::DateTime:
451 case QVariant::Time:
452 case QVariant::Double:
453 return true;
454 default:
455 return false;
456 }
457}
458
459QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.