diff options
author | Thiago Macieira <thiago@kde.org> | 2006-06-04 15:52:05 +0000 |
---|---|---|
committer | Thiago Macieira <thiago@kde.org> | 2006-06-04 15:52:05 +0000 |
commit | edbf2bfc109ce94b2604ea20328fda25542e4383 (patch) | |
tree | 3281d191fa9dde9f1f26b947b145d02373f031b0 /qt/src/qdbusxmlparser.cpp | |
parent | 435c7af9b605c3ffc8641142b6d7add18bf7080b (diff) |
* qt/: Update to Subversion r548032.
This includes a big reorganisation of the files inside the
subdir.
We really need a version control system that supports moving of
files. I'm not bothering with history anyways anymore, since the
bindings will be moved out to git. The history should be restored from
Subversion when that happens.
Diffstat (limited to 'qt/src/qdbusxmlparser.cpp')
-rw-r--r-- | qt/src/qdbusxmlparser.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/qt/src/qdbusxmlparser.cpp b/qt/src/qdbusxmlparser.cpp new file mode 100644 index 00000000..0370cb23 --- /dev/null +++ b/qt/src/qdbusxmlparser.cpp @@ -0,0 +1,308 @@ +/* -*- C++ -*- + * + * Copyright (C) 2005 Thiago Macieira <thiago@kde.org> + * Copyright (C) 2006 Trolltech AS. All rights reserved. + * Author: Thiago Macieira <thiago.macieira@trolltech.com> + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "qdbusxmlparser_p.h" +#include "qdbusinterface.h" +#include "qdbusinterface_p.h" +#include "qdbusconnection_p.h" +#include "qdbusutil.h" + +#include <QtXml/qdom.h> +#include <QtCore/qmap.h> +#include <QtCore/qvariant.h> +#include <QtCore/qtextstream.h> + +static QDBusIntrospection::Annotations +parseAnnotations(const QDomElement& elem) +{ + QDBusIntrospection::Annotations retval; + QDomNodeList list = elem.elementsByTagName(QLatin1String("annotation")); + for (int i = 0; i < list.count(); ++i) + { + QDomElement ann = list.item(i).toElement(); + if (ann.isNull()) + continue; + + QString name = ann.attribute(QLatin1String("name")), + value = ann.attribute(QLatin1String("value")); + + if (name.isEmpty()) + continue; + + retval.insert(name, value); + } + + return retval; +} + +static QDBusIntrospection::Arguments +parseArgs(const QDomElement& elem, const QLatin1String& direction, bool acceptEmpty = false) +{ + QDBusIntrospection::Arguments retval; + QDomNodeList list = elem.elementsByTagName(QLatin1String("arg")); + for (int i = 0; i < list.count(); ++i) + { + QDomElement arg = list.item(i).toElement(); + if (arg.isNull()) + continue; + + if ((acceptEmpty && !arg.hasAttribute(QLatin1String("direction"))) || + arg.attribute(QLatin1String("direction")) == direction) { + + QDBusIntrospection::Argument argData; + if (arg.hasAttribute(QLatin1String("name"))) + argData.name = arg.attribute(QLatin1String("name")); // can be empty + argData.type = arg.attribute(QLatin1String("type")); + if (!QDBusUtil::isValidSingleSignature(argData.type)) + continue; + + retval << argData; + } + } + return retval; +} + +QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path, + const QString& xmlData) + : m_service(service), m_path(path) +{ + QDomDocument doc; + doc.setContent(xmlData); + m_node = doc.firstChildElement(QLatin1String("node")); +} + +QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path, + const QDomElement& node) + : m_service(service), m_path(path), m_node(node) +{ +} + +QDBusIntrospection::Interfaces +QDBusXmlParser::interfaces() const +{ + QDBusIntrospection::Interfaces retval; + + if (m_node.isNull()) + return retval; + + QDomNodeList interfaces = m_node.elementsByTagName(QLatin1String("interface")); + for (int i = 0; i < interfaces.count(); ++i) + { + QDomElement iface = interfaces.item(i).toElement(); + QString ifaceName = iface.attribute(QLatin1String("name")); + if (iface.isNull() || ifaceName.isEmpty()) + continue; // for whatever reason + + QDBusIntrospection::Interface *ifaceData = new QDBusIntrospection::Interface; + ifaceData->name = ifaceName; + { + // save the data + QTextStream ts(&ifaceData->introspection); + iface.save(ts,2); + } + + // parse annotations + ifaceData->annotations = parseAnnotations(iface); + + // parse methods + QDomNodeList list = iface.elementsByTagName(QLatin1String("method")); + for (int j = 0; j < list.count(); ++j) + { + QDomElement method = list.item(j).toElement(); + QString methodName = method.attribute(QLatin1String("name")); + if (method.isNull() || methodName.isEmpty()) + continue; + + QDBusIntrospection::Method methodData; + methodData.name = methodName; + + // parse arguments + methodData.inputArgs = parseArgs(method, QLatin1String("in")); + methodData.outputArgs = parseArgs(method, QLatin1String("out")); + methodData.annotations = parseAnnotations(method); + + // add it + ifaceData->methods.insert(methodName, methodData); + } + + // parse signals + list = iface.elementsByTagName(QLatin1String("signal")); + for (int j = 0; j < list.count(); ++j) + { + QDomElement signal = list.item(j).toElement(); + QString signalName = signal.attribute(QLatin1String("name")); + if (signal.isNull() || signalName.isEmpty()) + continue; + + QDBusIntrospection::Signal signalData; + signalData.name = signalName; + + // parse data + signalData.outputArgs = parseArgs(signal, QLatin1String("out"), true); + signalData.annotations = parseAnnotations(signal); + + // add it + ifaceData->signals_.insert(signalName, signalData); + } + + // parse properties + list = iface.elementsByTagName(QLatin1String("property")); + for (int j = 0; j < list.count(); ++j) + { + QDomElement property = list.item(j).toElement(); + QString propertyName = property.attribute(QLatin1String("name")); + if (property.isNull() || propertyName.isEmpty()) + continue; + + QDBusIntrospection::Property propertyData; + + // parse data + propertyData.name = propertyName; + propertyData.type = property.attribute(QLatin1String("type")); + propertyData.annotations = parseAnnotations(property); + + if (!QDBusUtil::isValidSingleSignature(propertyData.type)) + // cannot be! + continue; + + QString access = property.attribute(QLatin1String("access")); + if (access.isEmpty()) + // can't be empty either! + continue; + else if (access == QLatin1String("read")) + propertyData.access = QDBusIntrospection::Property::Read; + else if (access == QLatin1String("write")) + propertyData.access = QDBusIntrospection::Property::Write; + else if (access == QLatin1String("readwrite")) + propertyData.access = QDBusIntrospection::Property::ReadWrite; + else + continue; // invalid one! + + // add it + ifaceData->properties.insert(propertyName, propertyData); + } + + // add it + retval.insert(ifaceName, QSharedDataPointer<QDBusIntrospection::Interface>(ifaceData)); + } + + return retval; +} + +QSharedDataPointer<QDBusIntrospection::Object> +QDBusXmlParser::object() const +{ + if (m_node.isNull()) + return QSharedDataPointer<QDBusIntrospection::Object>(); + + QDBusIntrospection::Object* objData; + objData = new QDBusIntrospection::Object; + objData->service = m_service; + objData->path = m_path; + + // check if we have anything to process + if (objData->introspection.isNull() && !m_node.firstChild().isNull()) { + // yes, introspect this object + QTextStream ts(&objData->introspection); + m_node.save(ts,2); + + QDomNodeList objects = m_node.elementsByTagName(QLatin1String("node")); + for (int i = 0; i < objects.count(); ++i) { + QDomElement obj = objects.item(i).toElement(); + QString objName = obj.attribute(QLatin1String("name")); + if (obj.isNull() || objName.isEmpty()) + continue; // for whatever reason + + objData->childObjects.append(objName); + } + + QDomNodeList interfaces = m_node.elementsByTagName(QLatin1String("interface")); + for (int i = 0; i < interfaces.count(); ++i) { + QDomElement iface = interfaces.item(i).toElement(); + QString ifaceName = iface.attribute(QLatin1String("name")); + if (iface.isNull() || ifaceName.isEmpty()) + continue; + + objData->interfaces.append(ifaceName); + } + } else { + objData->introspection = QLatin1String("<node/>\n"); + } + + QSharedDataPointer<QDBusIntrospection::Object> retval; + retval = objData; + return retval; +} + +QSharedDataPointer<QDBusIntrospection::ObjectTree> +QDBusXmlParser::objectTree() const +{ + QSharedDataPointer<QDBusIntrospection::ObjectTree> retval; + + if (m_node.isNull()) + return retval; + + retval = new QDBusIntrospection::ObjectTree; + + retval->service = m_service; + retval->path = m_path; + + QTextStream ts(&retval->introspection); + m_node.save(ts,2); + + // interfaces are easy: + retval->interfaceData = interfaces(); + retval->interfaces = retval->interfaceData.keys(); + + // sub-objects are slightly more difficult: + QDomNodeList objects = m_node.elementsByTagName(QLatin1String("node")); + for (int i = 0; i < objects.count(); ++i) { + QDomElement obj = objects.item(i).toElement(); + QString objName = obj.attribute(QLatin1String("name")); + if (obj.isNull() || objName.isEmpty()) + continue; // for whatever reason + + // check if we have anything to process + if (!obj.firstChild().isNull()) { + // yes, introspect this object + QString xml; + QTextStream ts(&xml); + obj.save(ts,0); + + // parse it + QString objAbsName = m_path; + if (!objAbsName.endsWith(QLatin1Char('/'))) + objAbsName.append(QLatin1Char('/')); + objAbsName += objName; + + QDBusXmlParser parser(m_service, objAbsName, obj); + retval->childObjectData.insert(objName, parser.objectTree()); + } + + retval->childObjects << objName; + } + + return QSharedDataPointer<QDBusIntrospection::ObjectTree>( retval ); +} + |