qobjectxmlmodel.cpp Example File xmlpatterns/qobjectxmlmodel/qobjectxmlmodel.cpp
#include <QVector>
#include <QtDebug>
#include <QCoreApplication>
#include <QMetaProperty>
#include <QXmlQuery>
#include <QXmlResultItems>
#include "qobjectxmlmodel.h"
QMetaProperty QObjectXmlModel::toMetaProperty(const QXmlNodeModelIndex &n)
{
const int propertyOffset = n.additionalData() & (~QObjectProperty);
const QObject *const qo = asQObject(n);
return qo->metaObject()->property(propertyOffset);
}
QObjectXmlModel::QObjectXmlModel(QObject *const object,
const QXmlNamePool &np) : QSimpleXmlNodeModel(np)
, m_baseURI(QUrl::fromLocalFile(QCoreApplication::applicationFilePath()))
, m_root(object)
, m_allMetaObjects(allMetaObjects())
{
Q_ASSERT(m_baseURI.isValid());
}
QXmlNodeModelIndex QObjectXmlModel::qObjectSibling(const int pos,
const QXmlNodeModelIndex &ni) const
{
Q_ASSERT(pos == 1 || pos == -1);
Q_ASSERT(asQObject(ni));
const QObject *parent = asQObject(ni)->parent();
if(parent)
{
const QList<QObject *> &children = parent->children();
const int siblingPos = children.indexOf(asQObject(ni)) + pos;
if(siblingPos >= 0 && siblingPos < children.count())
return createIndex(children.at(siblingPos));
else
return QXmlNodeModelIndex();
}
else
return QXmlNodeModelIndex();
}
QObjectXmlModel::QObjectNodeType QObjectXmlModel::toNodeType(const QXmlNodeModelIndex &ni)
{
return QObjectNodeType(ni.additionalData() & (15 << 26));
}
QObjectXmlModel::AllMetaObjects QObjectXmlModel::allMetaObjects() const
{
QXmlQuery query(namePool());
query.bindVariable("root", root());
query.setQuery("declare variable $root external;"
"$root/descendant-or-self::QObject");
Q_ASSERT(query.isValid());
QXmlResultItems result;
query.evaluateTo(&result);
QXmlItem i(result.next());
AllMetaObjects objects;
while(!i.isNull())
{
const QMetaObject *moo = asQObject(i.toNodeModelIndex())->metaObject();
while(moo)
{
if(!objects.contains(moo))
objects.append(moo);
moo = moo->superClass();
}
i = result.next();
}
Q_ASSERT(!objects.contains(0));
return objects;
}
QXmlNodeModelIndex QObjectXmlModel::metaObjectSibling(const int pos,
const QXmlNodeModelIndex &ni) const
{
Q_ASSERT(pos == 1 || pos == -1);
Q_ASSERT(!ni.isNull());
const int indexOf = m_allMetaObjects.indexOf(static_cast<const QMetaObject *>(ni.internalPointer())) + pos;
if(indexOf >= 0 && indexOf < m_allMetaObjects.count())
return createIndex(const_cast<QMetaObject *>(m_allMetaObjects.at(indexOf)), MetaObject);
else
return QXmlNodeModelIndex();
}
QXmlNodeModelIndex QObjectXmlModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &ni) const
{
switch(toNodeType(ni))
{
case MetaObjects:
{
switch(axis)
{
case Parent:
return QXmlNodeModelIndex();
case PreviousSibling:
return QXmlNodeModelIndex();
case NextSibling:
return root();
case FirstChild:
{
return createIndex(const_cast<QMetaObject *>(m_allMetaObjects.first()), MetaObject);
}
}
Q_ASSERT(false);
}
case MetaObject:
{
switch(axis)
{
case FirstChild:
return QXmlNodeModelIndex();
case Parent:
return createIndex(qint64(0), MetaObjects);
case PreviousSibling:
return metaObjectSibling(-1, ni);
case NextSibling:
return metaObjectSibling(1, ni);
}
}
case IsQObject:
{
switch(axis)
{
case Parent:
return createIndex(asQObject(ni)->parent());
case FirstChild:
{
if(!asQObject(ni) || asQObject(ni)->children().isEmpty())
return QXmlNodeModelIndex();
else
return createIndex(asQObject(ni)->children().first());
}
case PreviousSibling:
{
if(asQObject(ni) == m_root)
return createIndex(qint64(0), MetaObjects);
else
return qObjectSibling(-1, ni);
}
case NextSibling:
return qObjectSibling(1, ni);
}
Q_ASSERT(false);
}
case MetaObjectClassName:
case MetaObjectSuperClass:
{
Q_ASSERT(axis == Parent);
return createIndex(asQObject(ni), MetaObject);
}
case QObjectClassName:
case QObjectProperty:
{
Q_ASSERT(axis == Parent);
return createIndex(asQObject(ni));
}
}
Q_ASSERT(false);
return QXmlNodeModelIndex();
}
QVector<QXmlNodeModelIndex> QObjectXmlModel::attributes(const QXmlNodeModelIndex &ni) const
{
QVector<QXmlNodeModelIndex> result;
QObject *const object = asQObject(ni);
switch(toNodeType(ni))
{
case IsQObject:
{
const QMetaObject *const metaObject = object->metaObject();
const int count = metaObject->propertyCount();
result.append(createIndex(object, QObjectClassName));
for(int i = 0; i < count; ++i)
{
const QMetaProperty qmp(metaObject->property(i));
const int ii = metaObject->indexOfProperty(qmp.name());
if(i == ii)
result.append(createIndex(object, QObjectProperty | i));
}
return result;
}
case MetaObject:
{
result.append(createIndex(object, MetaObjectClassName));
result.append(createIndex(object, MetaObjectSuperClass));
return result;
}
default:
return QVector<QXmlNodeModelIndex>();
}
}
QObject *QObjectXmlModel::asQObject(const QXmlNodeModelIndex &n)
{
return static_cast<QObject *>(n.internalPointer());
}
bool QObjectXmlModel::isProperty(const QXmlNodeModelIndex n)
{
return n.additionalData() & QObjectProperty;
}
QUrl QObjectXmlModel::documentUri(const QXmlNodeModelIndex &) const
{
return m_baseURI;
}
QXmlNodeModelIndex::NodeKind QObjectXmlModel::kind(const QXmlNodeModelIndex &ni) const
{
switch(toNodeType(ni))
{
case IsQObject:
case MetaObject:
case MetaObjects:
return QXmlNodeModelIndex::Element;
case QObjectProperty:
case MetaObjectClassName:
case MetaObjectSuperClass:
case QObjectClassName:
return QXmlNodeModelIndex::Attribute;
}
Q_ASSERT(false);
return QXmlNodeModelIndex::Element;
}
QXmlNodeModelIndex::DocumentOrder QObjectXmlModel::compareOrder(const QXmlNodeModelIndex &, const QXmlNodeModelIndex &) const
{
return QXmlNodeModelIndex::Follows;
}
QXmlNodeModelIndex QObjectXmlModel::root() const
{
return createIndex(m_root);
}
QXmlNodeModelIndex QObjectXmlModel::root(const QXmlNodeModelIndex &n) const
{
QObject *p = asQObject(n);
Q_ASSERT(p);
do
{
QObject *const candidate = p->parent();
if(candidate)
p = candidate;
else
break;
}
while(true);
return createIndex(p);
}
QXmlNodeModelIndex QObjectXmlModel::parent(const QXmlNodeModelIndex &ni) const
{
QObject *const p = asQObject(ni)->parent();
if(p)
return createIndex(p);
else
return QXmlNodeModelIndex();
}
QXmlNodeModelIndex::List QObjectXmlModel::ancestors(const QXmlNodeModelIndex n) const
{
const QObject *p = asQObject(n);
Q_ASSERT(p);
QXmlNodeModelIndex::List result;
do
{
QObject *const candidate = p->parent();
if(candidate)
{
result.append(createIndex(candidate, 0));
p = candidate;
}
else
break;
}
while(true);
return result;
}
QXmlName QObjectXmlModel::name(const QXmlNodeModelIndex &ni) const
{
switch(toNodeType(ni))
{
case IsQObject:
return QXmlName(namePool(), QLatin1String("QObject"));
case MetaObject:
return QXmlName(namePool(), QLatin1String("metaObject"));
case QObjectClassName:
case MetaObjectClassName:
return QXmlName(namePool(), QLatin1String("className"));
case QObjectProperty:
return QXmlName(namePool(), toMetaProperty(ni).name());
case MetaObjects:
return QXmlName(namePool(), QLatin1String("metaObjects"));
case MetaObjectSuperClass:
return QXmlName(namePool(), QLatin1String("superClass"));
}
Q_ASSERT(false);
return QXmlName();
}
QVariant QObjectXmlModel::typedValue(const QXmlNodeModelIndex &n) const
{
switch(toNodeType(n))
{
case QObjectProperty:
{
const QVariant &candidate = toMetaProperty(n).read(asQObject(n));
if(isTypeSupported(candidate.type()))
return candidate;
else
return QVariant();
}
case MetaObjectClassName:
return QVariant(static_cast<QMetaObject *>(n.internalPointer())->className());
case MetaObjectSuperClass:
{
const QMetaObject *const superClass = static_cast<QMetaObject *>(n.internalPointer())->superClass();
if(superClass)
return QVariant(superClass->className());
else
return QVariant();
}
case QObjectClassName:
return QVariant(asQObject(n)->metaObject()->className());
default:
return QVariant();
}
}
bool QObjectXmlModel::isTypeSupported(QVariant::Type type)
{
switch(type)
{
case QVariant::Char:
case QVariant::String:
case QVariant::Url:
case QVariant::Bool:
case QVariant::ByteArray:
case QVariant::Int:
case QVariant::LongLong:
case QVariant::ULongLong:
case QVariant::Date:
case QVariant::DateTime:
case QVariant::Time:
case QVariant::Double:
return true;
default:
return false;
}
}
|
|
Best Of
Actualités les plus lues
Le blog Digia au hasard
Le blog Digia est l'endroit privilégié pour la communication sur l'édition commerciale de Qt, où des réponses publiques sont apportées aux questions les plus posées au support. Lire l'article.
Communauté
Ressources
Liens utiles
Contact
- Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).
Qt dans le magazine
|