From edbf2bfc109ce94b2604ea20328fda25542e4383 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 4 Jun 2006 15:52:05 +0000 Subject: * 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. --- qt/src/qdbusxmlparser.cpp | 308 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 qt/src/qdbusxmlparser.cpp (limited to 'qt/src/qdbusxmlparser.cpp') 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 + * Copyright (C) 2006 Trolltech AS. All rights reserved. + * Author: Thiago Macieira + * + * 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 +#include +#include +#include + +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(ifaceData)); + } + + return retval; +} + +QSharedDataPointer +QDBusXmlParser::object() const +{ + if (m_node.isNull()) + return QSharedDataPointer(); + + 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("\n"); + } + + QSharedDataPointer retval; + retval = objData; + return retval; +} + +QSharedDataPointer +QDBusXmlParser::objectTree() const +{ + QSharedDataPointer 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( retval ); +} + -- cgit