![]() |
Home · Examples |
This example shows how to use QtXmlPatterns to query QObject trees using XQuery by modeling the non-XML data structure of a QObject tree to look like XML.
Note: This page is not complete. Watch this space.
In this example, we want to model a QObject tree to look like XML. That is easy to do because QObject tree structures map simply to XML tree structures. Each QObject node is modeled as an XML element node. But when we try to include the QMetaObject tree in the model, we are adding a second tree to the mode, the QMetaObject tree, which exists behind the QObject tree, thus changing the two dimensional data structure into a three dimensional one.
By adding the QMetaObject tree to the node model and thereby making the model three dimensional, the query engine can no longer traverse it as if it were an XML document, because an XML document is always a two dimensional tree. This means if we want to include the QMetaObject tree in the node model, we have to somehow flatten it into the the same plane as the two dimensional QObject tree. This requires that our node model class must actually build an auxiliary component of the node model. How we do this and how this auxiliary structure is traversed is explained in Including The QMetaObject Tree.The User Interface
The UI for this example was created using Qt Designer: Code Walk-Through
The strategy for this example is different from the strategy for the file system example. In the file system example, the node model class had to actually build a node model, because the non-XML data to be traversed was the computer's file system, a structure stored on disk in a form that the query engine couldn't use. The node model class had to build an analog of the computer's file system in memory, and that in-memory structure was the node model.
For this example, the data structure to be traversed already exists in memory in a usable form. It is the QObject tree of the example application itself. All we need is the pointer to the root of the QObject tree.
Note: When we add the QMetaObject tree to the node model, the node model class will have to build an auxiliary data structure to move the QMetaObject tree into the same plane as the QObject tree. This is explained later in Including The QMetaObject Tree.The Custom Node Model Class: QObjextXmlModel
The node model class for this example is QObjextXmlModel, which is derived from QSimpleXmlNodeModel. QObjextXmlModel implements the callback interface functions that don't have implementations in QSimpleXmlNodeModel:
virtual QXmlNodeModelIndex::DocumentOrder compareOrder(const QXmlNodeModelIndex &n1, const QXmlNodeModelIndex &n2) const; virtual QXmlName name(const QXmlNodeModelIndex &n) const; virtual QUrl documentUri(const QXmlNodeModelIndex &n) const; virtual QXmlNodeModelIndex::NodeKind kind(const QXmlNodeModelIndex &n) const; virtual QXmlNodeModelIndex root(const QXmlNodeModelIndex &n) const; virtual QVariant typedValue(const QXmlNodeModelIndex &n) const; virtual QVector<QXmlNodeModelIndex> attributes(const QXmlNodeModelIndex&) const; virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis, const QXmlNodeModelIndex&) const;The node model class declares three data members:
const QUrl m_baseURI; QObject *const m_root; const AllMetaObjects m_allMetaObjects;m_baseURI is returned by documentUri(). m_root is the pointer to our node model, the already existing QObject tree for the example application itself. m_allMetaObjects will contain the auxiliary component of the node model required for including the QMetaObject tree in the node model. This is discussed in Including The QMetaObject Tree.
Since the node model is a QObject tree, we use a pointer to a QObject to uniquely identify a node in the node model. To get the QXmlNodeModelIndex for a QObject, we pass a pointer to the QObject to createIndex(), as in the root() function:
The following code example is written in c++.
QXmlNodeModelIndex QObjectXmlModel::root() const { return createIndex(m_root); }An overloading of root() allows finding the root node given the QXmlNodeModelIndex of any QObject in the node model:
QObjectXmlModel::QObjectNodeType QObjectXmlModel::toNodeType(const QXmlNodeModelIndex &n) { return QObjectNodeType(n.additionalData() & (15 << 26)); }
QXmlNodeModelIndex QObjectXmlModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &n) const { switch (toNodeType(n)) { case IsQObject: { switch (axis) { case Parent: return createIndex(asQObject(n)->parent()); case FirstChild: { if (!asQObject(n) || asQObject(n)->children().isEmpty()) return QXmlNodeModelIndex(); else return createIndex(asQObject(n)->children().first()); } case NextSibling: return qObjectSibling(1, n); case PreviousSibling: { if (asQObject(n) == m_root) return createIndex(qint64(0), MetaObjects); else return qObjectSibling(-1, n); } } Q_ASSERT(false); } case QObjectClassName: case QObjectProperty: { Q_ASSERT(axis == Parent); return createIndex(asQObject(n)); } } Q_ASSERT(false); return QXmlNodeModelIndex(); }
class MainWindow : public QMainWindow, private Ui_MainWindow { Q_OBJECT public: MainWindow(); private slots: void on_actionAbout_triggered(); };
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Trademarks | Qt Jambi 4.5.2_01 |