summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commite1b2c9deb5943faae2b29be6a5c006f75bb73f06 (patch)
treefc79e45367c0a8fc71185e9afc33f7503a58653c /tools
downloadqtxmlpatterns-e1b2c9deb5943faae2b29be6a5c006f75bb73f06.tar.gz
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tools')
-rw-r--r--tools/tools.pro2
-rw-r--r--tools/xmlpatterns/main.cpp386
-rw-r--r--tools/xmlpatterns/main.h66
-rw-r--r--tools/xmlpatterns/qapplicationargument.cpp344
-rw-r--r--tools/xmlpatterns/qapplicationargument_p.h101
-rw-r--r--tools/xmlpatterns/qapplicationargumentparser.cpp1028
-rw-r--r--tools/xmlpatterns/qapplicationargumentparser_p.h112
-rw-r--r--tools/xmlpatterns/xmlpatterns.pro28
-rw-r--r--tools/xmlpatternsvalidator/main.cpp130
-rw-r--r--tools/xmlpatternsvalidator/main.h74
-rw-r--r--tools/xmlpatternsvalidator/xmlpatternsvalidator.pro19
11 files changed, 2290 insertions, 0 deletions
diff --git a/tools/tools.pro b/tools/tools.pro
new file mode 100644
index 0000000..c2f1352
--- /dev/null
+++ b/tools/tools.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += xmlpatterns xmlpatternsvalidator
diff --git a/tools/xmlpatterns/main.cpp b/tools/xmlpatterns/main.cpp
new file mode 100644
index 0000000..552a13f
--- /dev/null
+++ b/tools/xmlpatterns/main.cpp
@@ -0,0 +1,386 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDir>
+#include <QtCore/QtDebug>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringList>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
+#include <QtCore/QVector>
+#include <QtCore/QCoreApplication>
+
+#include <QtXmlPatterns/QXmlFormatter>
+#include <QtXmlPatterns/QXmlItem>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QtXmlPatterns/QXmlSerializer>
+
+#include "private/qautoptr_p.h"
+#include "qapplicationargument_p.h"
+#include "qapplicationargumentparser_p.h"
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+/* Needed for opening stdout with _fdopen & friends. io.h seems to not be
+ * needed on MinGW though. */
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#include "main.h"
+
+QT_USE_NAMESPACE
+
+/* The two Q_DECLARE_METATYPE macros must appear before the code
+ * on a couple of HPUX platforms. */
+
+/*!
+ \internal
+ \since 4.4
+ Represents the name and value found in "-param name=value".
+ */
+typedef QPair<QString, QString> Parameter;
+Q_DECLARE_METATYPE(Parameter)
+
+/*!
+ \internal
+ \since 4.4
+ For the -output switch.
+ */
+Q_DECLARE_METATYPE(QIODevice *)
+
+/*!
+ \class PatternistApplicationParser
+ \brief Subclass to handle -param name=value
+ \internal
+ \since 4.4
+ \reentrant
+ */
+class PatternistApplicationParser : public QApplicationArgumentParser
+{
+public:
+ inline PatternistApplicationParser(int argc, char **argv,
+ const QXmlNamePool &np) : QApplicationArgumentParser(argc, argv)
+ , m_namePool(np)
+#ifdef Q_OS_WIN
+ , m_stdout(0)
+#endif
+ {
+ }
+
+#ifdef Q_OS_WIN
+ virtual ~PatternistApplicationParser()
+ {
+ /* QFile::~QFile() nor QFile::close() frees the handle when
+ * we use QFile::open() so we have to do it manually.
+ *
+ * "If stream is NULL, the invalid parameter handler is invoked," so
+ * lets try to avoid that. */
+ if(m_stdout)
+ fclose(m_stdout);
+ }
+#endif
+
+protected:
+ virtual QVariant convertToValue(const QApplicationArgument &arg,
+ const QString &input) const
+ {
+ if(arg.name() == QLatin1String("param"))
+ {
+ const int assign = input.indexOf(QLatin1Char('='));
+
+ if(assign == -1)
+ {
+ message(QXmlPatternistCLI::tr("Each binding must contain an equal sign."));
+ return QVariant();
+ }
+
+ const QString name(input.left(assign));
+ const QString value(input.mid(assign + 1));
+
+ if(!QXmlName::isNCName(name))
+ {
+ message(QXmlPatternistCLI::tr("The variable name must be a valid NCName, which %1 isn't.").arg(name));
+ return QVariant();
+ }
+
+ /* The value.isNull() check ensures we can bind variables whose value is an empty string. */
+ return QVariant::fromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value ));
+ }
+ else if(arg.name() == QLatin1String("output"))
+ {
+ QFile *const f = new QFile(input);
+
+ if(f->open(QIODevice::WriteOnly))
+ return QVariant::fromValue(static_cast<QIODevice *>(f));
+ else
+ {
+ message(QXmlPatternistCLI::tr("Failed to open file %1 for writing: %2").arg(f->fileName(), f->errorString()));
+ return QVariant();
+ }
+ }
+ else if(arg.name() == QLatin1String("initial-template"))
+ {
+ const QXmlName name(QXmlName::fromClarkName(input, m_namePool));
+ if(name.isNull())
+ {
+ message(QXmlPatternistCLI::tr("%1 is an invalid Clark Name").arg(input));
+ return QVariant();
+ }
+ else
+ return QVariant::fromValue(name);
+ }
+ else
+ return QApplicationArgumentParser::convertToValue(arg, input);
+ }
+
+ virtual QString typeToName(const QApplicationArgument &argument) const
+ {
+ if(argument.name() == QLatin1String("param"))
+ return QLatin1String("name=value");
+ else if(argument.name() == QLatin1String("output"))
+ return QLatin1String("local file");
+ else
+ return QApplicationArgumentParser::typeToName(argument);
+ }
+
+ virtual QVariant defaultValue(const QApplicationArgument &argument) const
+ {
+ if(argument.name() == QLatin1String("output"))
+ {
+ QFile *const out = new QFile();
+
+#ifdef Q_OS_WIN
+ /* If we don't open stdout in "binary" mode on Windows, it will translate
+ * 0xA into 0xD 0xA. */
+ _setmode(_fileno(stdout), _O_BINARY);
+ m_stdout = _wfdopen(_fileno(stdout), L"wb");
+ out->open(m_stdout, QIODevice::WriteOnly);
+#else
+ out->open(stdout, QIODevice::WriteOnly);
+#endif
+
+ return QVariant::fromValue(static_cast<QIODevice *>(out));
+ }
+ else
+ return QApplicationArgumentParser::defaultValue(argument);
+ }
+
+private:
+ QXmlNamePool m_namePool;
+#ifdef Q_OS_WIN
+ mutable FILE * m_stdout;
+#endif
+};
+
+static inline QUrl finalizeURI(const QApplicationArgumentParser &parser,
+ const QApplicationArgument &isURI,
+ const QApplicationArgument &arg)
+{
+ QUrl userURI;
+ {
+ const QString stringURI(parser.value(arg).toString());
+
+ if(parser.has(isURI))
+ userURI = QUrl::fromEncoded(stringURI.toLatin1());
+ else
+ userURI = QUrl::fromLocalFile(stringURI);
+ }
+
+ return QUrl::fromLocalFile(QDir::current().absolutePath() + QLatin1Char('/')).resolved(userURI);
+}
+
+int main(int argc, char **argv)
+{
+ enum ExitCode
+ {
+ /**
+ * We start from 2, because QApplicationArgumentParser
+ * uses 1.
+ */
+ QueryFailure = 2,
+ StdOutFailure
+ };
+
+ const QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationName(QLatin1String("xmlpatterns"));
+
+ QXmlNamePool namePool;
+ PatternistApplicationParser parser(argc, argv, namePool);
+ parser.setApplicationDescription(QLatin1String("A tool for running XQuery queries."));
+ parser.setApplicationVersion(QLatin1String("0.1"));
+
+ QApplicationArgument param(QLatin1String("param"),
+ QXmlPatternistCLI::tr("Binds an external variable. The value is directly available using the variable reference: $name."),
+ qMetaTypeId<Parameter>());
+ param.setMaximumOccurrence(-1);
+ parser.addArgument(param);
+
+ const QApplicationArgument noformat(QLatin1String("no-format"),
+ QXmlPatternistCLI::tr("By default output is formatted for readability. When specified, strict serialization is performed."));
+ parser.addArgument(noformat);
+
+ const QApplicationArgument isURI(QLatin1String("is-uri"),
+ QXmlPatternistCLI::tr("If specified, all filenames on the command line are interpreted as URIs instead of a local filenames."));
+ parser.addArgument(isURI);
+
+ const QApplicationArgument initialTemplateName(QLatin1String("initial-template"),
+ QXmlPatternistCLI::tr("The name of the initial template to call as a Clark Name."),
+ QVariant::String);
+ parser.addArgument(initialTemplateName);
+
+ /* The temporary object is required to compile with g++ 3.3. */
+ QApplicationArgument queryURI = QApplicationArgument(QLatin1String("query/stylesheet"),
+ QXmlPatternistCLI::tr("A local filename pointing to the query to run. If the name ends with .xsl it's assumed "
+ "to be an XSL-T stylesheet. If it ends with .xq, it's assumed to be an XQuery query. (In "
+ "other cases it's also assumed to be an XQuery query, but that interpretation may "
+ "change in a future release of Qt.)"),
+ QVariant::String);
+ queryURI.setMinimumOccurrence(1);
+ queryURI.setNameless(true);
+ parser.addArgument(queryURI);
+
+ QApplicationArgument focus = QApplicationArgument(QLatin1String("focus"),
+ QXmlPatternistCLI::tr("The document to use as focus. Mandatory "
+ "in case a stylesheet is used. This option is "
+ "also affected by the is-uris option."),
+ QVariant::String);
+ focus.setMinimumOccurrence(0);
+ focus.setNameless(true);
+ parser.addArgument(focus);
+
+ QApplicationArgument output(QLatin1String("output"),
+ QXmlPatternistCLI::tr("A local file to which the output should be written. "
+ "The file is overwritten, or if not exist, created. "
+ "If absent, stdout is used."),
+ qMetaTypeId<QIODevice *>());
+ parser.addArgument(output);
+
+ if(!parser.parse())
+ return parser.exitCode();
+
+ /* Get the query URI. */
+ const QUrl effectiveURI(finalizeURI(parser, isURI, queryURI));
+
+ QXmlQuery::QueryLanguage lang;
+
+ if(effectiveURI.toString().endsWith(QLatin1String(".xsl")))
+ lang = QXmlQuery::XSLT20;
+ else
+ lang = QXmlQuery::XQuery10;
+
+ if(lang == QXmlQuery::XQuery10 && parser.has(initialTemplateName))
+ {
+ parser.message(QXmlPatternistCLI::tr("An initial template name cannot be specified when running an XQuery."));
+ return QApplicationArgumentParser::ParseError;
+ }
+
+ QXmlQuery query(lang, namePool);
+
+ query.setInitialTemplateName(qvariant_cast<QXmlName>(parser.value(initialTemplateName)));
+
+ /* Bind external variables. */
+ {
+ const QVariantList parameters(parser.values(param));
+ const int len = parameters.count();
+
+ /* For tracking duplicates. */
+ QSet<QString> usedParameters;
+
+ for(int i = 0; i < len; ++i)
+ {
+ const Parameter p(qvariant_cast<Parameter>(parameters.at(i)));
+
+ if(usedParameters.contains(p.first))
+ {
+ parser.message(QXmlPatternistCLI::tr("Each parameter must be unique, %1 is specified at least twice.").arg(p.first));
+ return QApplicationArgumentParser::ParseError;
+ }
+ else
+ {
+ usedParameters.insert(p.first);
+ query.bindVariable(p.first, QXmlItem(p.second));
+ }
+ }
+ }
+
+ if(parser.has(focus))
+ {
+ if(!query.setFocus(finalizeURI(parser, isURI, focus)))
+ return QueryFailure;
+ }
+ else if(lang == QXmlQuery::XSLT20 && !parser.has(initialTemplateName))
+ {
+ parser.message(QXmlPatternistCLI::tr("When a stylesheet is used, a "
+ "document must be specified as a focus, or an "
+ "initial template name must be specified, or both."));
+ return QApplicationArgumentParser::ParseError;
+ }
+
+ query.setQuery(effectiveURI);
+
+ const QPatternist::AutoPtr<QIODevice> outDevice(qvariant_cast<QIODevice *>(parser.value(output)));
+ Q_ASSERT(outDevice);
+ Q_ASSERT(outDevice->isWritable());
+
+ if(query.isValid())
+ {
+ typedef QPatternist::AutoPtr<QAbstractXmlReceiver> RecPtr;
+ RecPtr receiver;
+
+ if(parser.has(noformat))
+ receiver = RecPtr(new QXmlSerializer(query, outDevice.data()));
+ else
+ receiver = RecPtr(new QXmlFormatter(query, outDevice.data()));
+
+ const bool success = query.evaluateTo(receiver.data());
+
+ if(success)
+ return parser.exitCode();
+ else
+ return QueryFailure;
+ }
+ else
+ return QueryFailure;
+}
+
diff --git a/tools/xmlpatterns/main.h b/tools/xmlpatterns/main.h
new file mode 100644
index 0000000..231fe06
--- /dev/null
+++ b/tools/xmlpatterns/main.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the XMLPatterns module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_main_h
+#define Patternist_main_h
+
+#include <QCoreApplication>
+
+class QXmlPatternistCLI
+{
+public:
+ Q_DECLARE_TR_FUNCTIONS(QXmlPatternistCLI)
+private:
+ inline QXmlPatternistCLI();
+ Q_DISABLE_COPY(QXmlPatternistCLI)
+};
+
+#endif
diff --git a/tools/xmlpatterns/qapplicationargument.cpp b/tools/xmlpatterns/qapplicationargument.cpp
new file mode 100644
index 0000000..3a359da
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargument.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QHash>
+#include <QString>
+
+#include "qapplicationargument_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QApplicationArgument
+ \brief The QApplicationArgument class is a declared of a command line
+ argument for QApplicationArgumentParser.
+ \reentrant
+ \internal
+ \since 4.4
+
+ QApplicationArgument describes a valid command line argument,
+ by having a set of characteristics:
+
+ \table
+ \header
+ \o Characteristic
+ \o Functions
+ \row
+ \o A name. For instance, "backend"
+ \o setName() and name()
+ \row
+ \o A description, for human consumption.
+ \o setDescription() and description()
+ \row
+ \o How many times the argument can occur. For instance, whether the argument is optional or not.
+ \o setMinimumOccurrence() & minimumOccurrence(), setMaximumOccurrence() & maximumOccurrence()
+ \row
+ \o The type of the argument's value, if it has one. For instance, \c int or \c bool.
+ \o setType() and type()
+ \row
+ \o The value that should be used in case the argument isn't used.
+ \o setDefaultValue() and defaultValue()
+ \endtable
+
+ \sa QApplicationArgumentParser
+ */
+
+class QApplicationArgumentPrivate
+{
+public:
+ inline QApplicationArgumentPrivate(const QString &newName,
+ const QString &desc,
+ const int newType) : name(newName)
+ , description(desc)
+ , type(newType)
+ , minimum(0)
+ , maximum(1)
+ , isNameless(false)
+ {
+ }
+
+ QString name;
+ QString description;
+ int type;
+ QVariant defaultValue;
+ int minimum;
+ int maximum;
+ bool isNameless;
+};
+
+/*!
+ Constructs an invalid QApplicationArgument instance.
+ */
+QApplicationArgument::QApplicationArgument() : d_ptr(new QApplicationArgumentPrivate(QString(), QString(), QVariant::Invalid))
+{
+}
+
+/*!
+ Constructs an QApplicationArgument instance that is a copy of \a other.
+ */
+QApplicationArgument::QApplicationArgument(const QApplicationArgument &other) : d_ptr(new QApplicationArgumentPrivate(*other.d_ptr))
+{
+}
+
+/*!
+ Destructs this QApplicationArgument instance.
+ */
+QApplicationArgument::~QApplicationArgument()
+{
+ delete d_ptr;
+}
+
+/*!
+ Constructs an argument that has the name \a name and is of type
+ \a aType.
+
+ Calling this constructor is equivalent to calling setName() and setType()
+ on a default constructed QApplicationArgument instance.
+
+ \sa setName(), setType()
+ */
+QApplicationArgument::QApplicationArgument(const QString &name,
+ const QString &description,
+ int aType) : d_ptr(new QApplicationArgumentPrivate(name, description, aType))
+{
+}
+
+/*!
+ Assigns \a other to this QApplicationArgument instance.
+ */
+QApplicationArgument &QApplicationArgument::operator=(const QApplicationArgument &other)
+{
+ if(this != &other)
+ *d_ptr = *other.d_ptr;
+
+ return *this;
+}
+
+// TODO is this really what we want?
+/*!
+ Returns true if this QApplicationArgument instance is equal to \a other.
+
+ Equalness is defined to only consider name(). If for instance the type() differs
+ but the names are equal, this operator will return \c true.
+ */
+bool QApplicationArgument::operator==(const QApplicationArgument &other) const
+{
+ return name() == other.name();
+}
+
+/*!
+ \fn qHash(const QApplicationArgument &);
+ \internal
+
+ Returns a hash index of \a argument. This function is used when QApplicationArgument
+ is used with QHash.
+
+ The hash index is computed on name(). The other properties are ignored.
+
+ \relates QApplicationArgument
+ */
+
+/*!
+ Sets this argument's name to \a newName. The name does not
+ include any dash, or other prefix that is used by the parser.
+ */
+void QApplicationArgument::setName(const QString &newName)
+{
+ d_ptr->name = newName;
+}
+
+/*!
+ Returns the name that this argument has.
+
+ \sa setName()
+ */
+QString QApplicationArgument::name() const
+{
+ return d_ptr->name;
+}
+
+/*!
+ Sets the tupe to \a newType.
+
+ If \a newType is QVariant::Invalid, it signals that this
+ argument does not accept a value at all.
+
+ \a newType can be a QVariant::type() value, or QVariant::userType().
+
+ \sa type()
+ */
+void QApplicationArgument::setType(int newType)
+{
+ d_ptr->type = newType;
+}
+
+/*!
+ Returns the type that the value of this argument has. If it
+ is QVariant::Invalid, it means this argument cannot have a value
+ and is a switch only.
+
+ The type is by default QVariant::Invalid.
+\sa setType()
+ */
+int QApplicationArgument::type() const
+{
+ return d_ptr->type;
+}
+
+void QApplicationArgument::setDefaultValue(const QVariant &value)
+{
+ d_ptr->defaultValue = value;
+}
+
+QVariant QApplicationArgument::defaultValue() const
+{
+ return d_ptr->defaultValue;
+}
+
+/*!
+ Sets the minimum amount of times this argument can occur, to \a minimum.
+ For instance, if \a minimum is 2, the argument must be used at least two times.
+
+ If \a minimum is zero, it means the argument is optional.
+
+ \sa minimumOccurrence(), setMaximumOccurrence()
+ */
+void QApplicationArgument::setMinimumOccurrence(int minimum)
+{
+ Q_ASSERT_X(minimum >= 0, Q_FUNC_INFO,
+ "The minimum cannot be less than zero.");
+ d_ptr->minimum = minimum;
+}
+
+/*!
+ Returns the minimum amount of times an an argument must occur.
+
+ The default is 0.
+
+ \sa setMinimumOccurrence(), maximumOccurrence()
+ */
+int QApplicationArgument::minimumOccurrence() const
+{
+ return d_ptr->minimum;
+}
+
+/*!
+ Sets the maximum occurrence to \a maximum.
+
+ If \a maximum is -1, it means the argument can appear an unlimited
+ amount of times. Setting it to zero or less than -1, yields
+ undefined behavior.
+
+\sa maximumOccurrence(), setMinimumOccurrence()
+ */
+void QApplicationArgument::setMaximumOccurrence(int maximum)
+{
+ Q_ASSERT_X(maximum == -1 || maximum >= 1, Q_FUNC_INFO,
+ "The maximum can only be -1 or 1 or larger.");
+ d_ptr->maximum = maximum;
+}
+
+/*!
+ Returns the maximum amount of times this argument can occur. For instance,
+ if the maximum occurrence is 2, it would be an error if 3 were specified
+ on the command line.
+
+ If the maximum occurrence is -1, it signals the argument can appear an unlimited
+ amount of times.
+
+ The default is 1.
+
+ \sa setMaximumOccurrence()
+ */
+int QApplicationArgument::maximumOccurrence() const
+{
+ return d_ptr->maximum;
+}
+
+/*!
+ Sets the description to \a newDescription. The description
+ should describe the argument in a sentence or two. It is used
+ when displaying a help message, if requested.
+
+ The description should be terminated as if it was a paragraph. This
+ typically means a period.
+
+ The description should be translated by wrapping the
+ string literal in a call to tr().
+
+ */
+void QApplicationArgument::setDescription(const QString &newDescription)
+{
+ d_ptr->description = newDescription;
+}
+
+/*!
+ Returns the description of this argument.
+
+ \sa setDescription()
+ */
+QString QApplicationArgument::description() const
+{
+ return d_ptr->description;
+}
+
+/*!
+ \internal
+ \relates QApplicationArgument
+
+ Computes a hash key on \a argument's name and returns it.
+ */
+uint qHash(const QApplicationArgument &argument)
+{
+ return qHash(argument.name());
+}
+
+void QApplicationArgument::setNameless(bool value)
+{
+ d_ptr->isNameless = value;
+}
+
+bool QApplicationArgument::isNameless() const
+{
+ return d_ptr->isNameless;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/xmlpatterns/qapplicationargument_p.h b/tools/xmlpatterns/qapplicationargument_p.h
new file mode 100644
index 0000000..c35ae45
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargument_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QApplicationArgument_H
+#define QApplicationArgument_H
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QApplicationArgumentPrivate;
+
+class QApplicationArgument
+{
+public:
+ QApplicationArgument();
+ QApplicationArgument(const QApplicationArgument &other);
+ QApplicationArgument(const QString &name,
+ const QString &description,
+ int aType = QVariant::Invalid);
+ ~QApplicationArgument();
+ QApplicationArgument &operator=(const QApplicationArgument &other);
+ bool operator==(const QApplicationArgument &other) const;
+
+ void setName(const QString &newName);
+ QString name() const;
+ void setDescription(const QString &newDescription);
+ QString description() const;
+
+ int type() const;
+ void setType(int newType);
+ void setDefaultValue(const QVariant &value);
+ QVariant defaultValue() const;
+
+ void setMinimumOccurrence(int minimum);
+ int minimumOccurrence() const;
+ void setMaximumOccurrence(int maximum);
+ int maximumOccurrence() const;
+ void setNameless(bool value);
+ bool isNameless() const;
+
+private:
+ QApplicationArgumentPrivate *d_ptr;
+};
+
+uint qHash(const QApplicationArgument &argument);
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
+
diff --git a/tools/xmlpatterns/qapplicationargumentparser.cpp b/tools/xmlpatterns/qapplicationargumentparser.cpp
new file mode 100644
index 0000000..2f4f424
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargumentparser.cpp
@@ -0,0 +1,1028 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDebug>
+#include <QTextBoundaryFinder>
+#include <QCoreApplication>
+#include <QHash>
+#include <QPair>
+#include <QStringList>
+#include <QTextStream>
+#include <QUrl>
+
+#include "qapplicationargument_p.h"
+
+#include "qapplicationargumentparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QApplicationArgumentParser
+ \brief The QApplicationArgumentParser class parses the command
+ line arguments for an application.
+ \reentrant
+ \internal
+ \since 4.4
+
+ QApplicationArgumentParser simplifies writing command line applications by taking care of:
+
+ \list
+ \o Generating help and version arguments
+ \o Taking care of converting arguments to QVariant types, since each argument
+ has a type: QApplicationArgument::type()
+ \o Validates the command line such that the user operates on well-defined input. For instance,
+ that the argument is a valid integer if that is the case, that an argument does not
+ occur more times than allowed, and so on.
+ \o Allows customization through sub-classing.
+ \endlist
+
+ The user declares what arguments that can be given to the application with QApplicationArgument. Provided
+ with that information, QApplicationArgumentParser takes care of parsing the actual
+ command line, appropriately flag errors, generate help messages, and provide
+ convenient access to the values of the arguments.
+
+ The way to use it is to create a set of QApplicationArgument by ones choosing, call
+ addArgument() for each, and subsequently call parse(). If parse() returns \c false,
+ the caller should exit and return exitCode().
+
+ If parse() returns \c true the command line was successfully parsed, its
+ values are well-defined, and they can be spectated with count(),
+ has(), value() and values().
+
+ \snippet doc/src/snippets/code/tools_patternist_qapplicationargumentparser.cpp 0
+
+ For arguments without a name(such as filename passed to the \c ls utility on Linux) add a
+ QApplicationArgument that does not have a name. The minimum and maximum occurrences will be
+ respected as usual and the type applies too.
+
+ QApplicationArgumentParser always has two options builtin: \c version and \c help.
+
+ \section1 Changing Parsing Convention
+
+ QApplicationArgumentParser by default parses the command line in the style
+ of Qt's utilities, where arguments are preceded by a single dash, and identified
+ by a single name. However, in some cases it might be of interest to parse
+ another style, such as the well-established UNIX \c getopt convention(\c -l
+ and \c --long).
+
+ This can be achieved by sub-classing QApplicationArgumentParser and reimplementing
+ parse(). It would do the following:
+
+ \list
+ \o Call input() to retrieve the strings the user specified on the command line.
+ \o Call declaredArguments() to retrieve the arguments that the implementor has
+ decided can be specified.
+ \o Parse and validate the input. Salt and pepper as per taste.
+ \o If an error occurred, call setExitCode() and return \c false.
+ \o Otherwise, call setExitCode(Success), provide access to the
+ arguments by calling setUsedArguments(), and return \c true. If a
+ help message was requested, call setExitCode(Success) and return \c false.
+ \endlist
+
+ \sa QApplicationArgument, QCoreApplication
+*/
+class QApplicationArgumentParserPrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(QApplicationArgumentParserPrivate)
+public:
+ // TODO Isn't it like ten times better with QHash<QApplicationArgument, QList<QVariant> >?
+ // TODO test QApplicationArgument::nameless()
+ typedef QList<QPair<QApplicationArgument, QVariant> > UsedList;
+
+ /*!
+ We initialize exitCode to ParseError such that we consciously flag success.
+ */
+ inline QApplicationArgumentParserPrivate(QApplicationArgumentParser *const master,
+ const QStringList &aInput) : exitCode(QApplicationArgumentParser::ParseError)
+ , input(aInput)
+ , q_ptr(master)
+ {
+ Q_ASSERT(!aInput.isEmpty());
+ }
+
+ QApplicationArgument nextNamelessArgument() const;
+ static QStringList argumentsFromLocal(const int argc, const char *const *const argv);
+
+ bool error(const QString &message);
+ static bool errorMessage(const QString &message);
+ static inline bool isSwitch(const QApplicationArgument &arg);
+ static inline QVariant conversionError(const QString &typeName,
+ const QString &input);
+ int count(const QApplicationArgument &arg) const;
+ bool contains(const QApplicationArgument &arg) const;
+ static inline bool isBuiltinVariant(const int type);
+ void displayVersion() const;
+ void displayHelp() const;
+ void parseNameless();
+ bool parseNamelessArguments(const QString &in);
+
+ QApplicationArgumentParser::ExitCode exitCode;
+ const QStringList input;
+
+ /*!
+ Since the QString is QApplicationArgument::name() anyway, why
+ not use a QSet?
+ */
+ QHash<QString, QApplicationArgument> declaredArguments;
+
+ QList<QApplicationArgument> declaredNamelessArguments;
+
+ UsedList usedArguments;
+ QString applicationDescription;
+ QString applicationVersion;
+
+private:
+ QApplicationArgumentParser *const q_ptr;
+ Q_DECLARE_PUBLIC(QApplicationArgumentParser)
+
+ static QString lineWrap(const QString &input,
+ const int leftIndent,
+ const int width);
+ static QList<QApplicationArgument> builtinArguments();
+};
+
+QApplicationArgument QApplicationArgumentParserPrivate::nextNamelessArgument() const
+{
+ /* Count how many nameless arguments we have so far. */
+ int count = 0;
+
+ for(int i = 0; i < usedArguments.count(); ++i)
+ {
+ if(usedArguments.at(i).first.isNameless())
+ ++count;
+ }
+
+ /* TODO this doesn't work for arguments that have more than one
+ * mandatory value(e.g nameless ones), since several values should
+ * then only count for one argument. */
+ for(int i = 0; i < declaredNamelessArguments.count(); ++i)
+ {
+ if(count)
+ {
+ /* Skip the ones we already have processed. */
+ --count;
+ continue;
+ }
+
+ if(declaredNamelessArguments.at(i).isNameless())
+ return declaredNamelessArguments.at(i);
+ }
+
+ return QApplicationArgument();
+}
+
+int QApplicationArgumentParserPrivate::count(const QApplicationArgument &arg) const
+{
+ const int len = usedArguments.count();
+ int count = 0;
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(usedArguments.at(i).first == arg)
+ ++count;
+ }
+
+ return count;
+}
+
+/*!
+ Returns \c true if \a arg has appeared on the command line, not whether it has been declared.
+ */
+bool QApplicationArgumentParserPrivate::contains(const QApplicationArgument &arg) const
+{
+ const int len = usedArguments.count();
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(usedArguments.at(i).first == arg)
+ return true;
+ }
+
+ return false;
+}
+
+/*!
+ Returns always \c false.
+ */
+bool QApplicationArgumentParserPrivate::error(const QString &message)
+{
+ exitCode = QApplicationArgumentParser::ParseError;
+ errorMessage(message);
+ return errorMessage(tr("Pass -help for information about the command line."));
+}
+
+/*!
+ Returns always \c false.
+ */
+bool QApplicationArgumentParserPrivate::errorMessage(const QString &message)
+{
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << message << endl;
+ return false;
+}
+
+/*!
+ \internal
+ Determines whether \a arg carries a value or is on/off.
+ */
+bool QApplicationArgumentParserPrivate::isSwitch(const QApplicationArgument &arg)
+{
+ return arg.type() == QVariant::Invalid;
+}
+
+QVariant QApplicationArgumentParserPrivate::conversionError(const QString &typeName,
+ const QString &input)
+{
+ errorMessage(tr("Cannot convert %1 to type %2.").arg(input, typeName));
+ return QVariant();
+}
+
+bool QApplicationArgumentParserPrivate::isBuiltinVariant(const int type)
+{
+ return type < int(QVariant::UserType);
+}
+
+/*!
+ TODO Temporary, replace with a function in QCoreApplication.
+*/
+QStringList QApplicationArgumentParserPrivate::argumentsFromLocal(const int argc, const char *const *const argv)
+{
+ Q_ASSERT(argc >= 1);
+ Q_ASSERT(argv);
+ QStringList result;
+
+ for(int i = 0; i < argc; ++i)
+ result.append(QString::fromLocal8Bit(argv[i]));
+
+ return result;
+}
+
+void QApplicationArgumentParserPrivate::displayVersion() const
+{
+ QTextStream out(stderr);
+
+ out << tr("%1 version %2 using Qt %3").arg(QCoreApplication::applicationName(), applicationVersion, QString::fromAscii(qVersion()))
+ << endl;
+}
+
+/*!
+ \internal
+ \relates QApplicationArgument
+
+ qLess() functor for QApplicationArgument that considers the name.
+ */
+template<>
+class qLess <QApplicationArgument>
+{
+public:
+ inline bool operator()(const QApplicationArgument &o1,
+ const QApplicationArgument &o2) const
+ {
+ return o1.name().compare(o2.name()) < 0;
+ }
+};
+
+void QApplicationArgumentParserPrivate::displayHelp() const
+{
+ enum Constants
+ {
+ /**
+ * When we want to line wrap, 80 minus a couple of characters. This should
+ * be suitable for vt100 compatible terminals.
+ */
+ LineWrapAt = 78,
+
+ /**
+ * The initial " -" for each option.
+ */
+ IndentPadding = 3,
+
+ /**
+ * Pad for the brackets and space we use when we have a type.
+ */
+ ValueArgumentPadding = 4
+ };
+
+ QList<QApplicationArgument> args(declaredArguments.values());
+ args += builtinArguments();
+
+ /* Sort them, such that we get the nameless options at the end, and it
+ * generally looks tidy. */
+ qSort(args);
+
+ /* This is the basic approach:
+ * Switches:
+ * -name description
+ * Value arguments:
+ * -name <name-of-value-type> description
+ *
+ * Nameless arguments
+ * name <type> description
+ *
+ * It all line-wraps at OutputWidth and the description is indented,
+ * where the highest indent is the length of the name plus length of the name
+ * of the type. */
+
+ /* First we find the name with the largest width. */
+ int maxWidth = 0;
+
+ QList<QApplicationArgument> nameless(declaredNamelessArguments);
+ qSort(nameless);
+
+ /* Note, here the nameless arguments appear last, but are sorted
+ * with themselves. */
+ QList<QApplicationArgument> allArgs(args + nameless);
+ const int allArgsCount = allArgs.count();
+
+ for(int i = 0; i < allArgsCount; ++i)
+ {
+ const QApplicationArgument &at = allArgs.at(i);
+ const int nameLength = at.name().length();
+ const QString typeName(q_ptr->typeToName(at));
+ const int typeNameLength = typeName.length();
+ const int padding = at.type() == QVariant::Invalid ? 0 : ValueArgumentPadding;
+ maxWidth = qMax(maxWidth, nameLength + typeNameLength + padding);
+ }
+
+ QTextStream out(stderr);
+ out << endl
+ << QString(IndentPadding, QLatin1Char(' '))
+ << QCoreApplication::applicationName()
+ << QLatin1String(" -- ")
+ << applicationDescription
+ << endl;
+ // TODO synopsis
+
+ /* One extra so we get some space between the overview and the options. */
+ out << endl;
+
+ const int indentWidth = maxWidth + 3;
+
+ /* Ok, print them out. */
+ for(int i = 0; i < allArgsCount; ++i)
+ {
+ const QApplicationArgument &at = allArgs.at(i);
+ /* " -name ". Indent a bit first, inspired by Qt's moc. */
+ const QString &name = at.name();
+ QString prolog(QLatin1String(" "));
+
+ /* We have a special case for the single dash. */
+ if(name == QChar::fromLatin1('-'))
+ prolog.append(name);
+ else
+ {
+ if(!at.isNameless())
+ prolog.append(QLatin1Char('-'));
+
+ prolog.append(name + QLatin1Char(' '));
+ }
+
+ if(at.type() != QVariant::Invalid)
+ {
+ /* It's not a switch, it has a value. */
+
+ /* Do we have a default value? If so, the argument is optional. */
+ const QString typeName(q_ptr->typeToName(at));
+
+ if(at.defaultValue().isValid())
+ prolog.append(QLatin1Char('[') + typeName + QLatin1Char(']'));
+ else
+ prolog.append(QLatin1Char('<') + typeName + QLatin1Char('>'));
+ // TODO Don't we want to display the default value?
+
+ prolog.append(QLatin1Char(' '));
+ }
+
+ prolog = prolog.leftJustified(indentWidth);
+
+ out << prolog
+ << lineWrap(at.description(), indentWidth, LineWrapAt)
+ << endl;
+ }
+}
+
+/*!
+ Line wraps \a input and indents each line with \a leftIndent spaces, such that
+ the width does not go beyond \a maxWidth.
+
+ The addition of line endings is accounted for by the caller.
+
+ With QTextBoundaryFinder our line wrapping is relatively fancy, since it
+ does it the Unicode-way.
+ */
+QString QApplicationArgumentParserPrivate::lineWrap(const QString &input,
+ const int leftIndent,
+ const int maxWidth)
+{
+ const QString indent(QString(leftIndent, QLatin1Char(' ')));
+ const int len = input.length();
+ const int textWidth = maxWidth - leftIndent;
+
+ QString output;
+ QTextBoundaryFinder wrapFinder(QTextBoundaryFinder::Line, input);
+ wrapFinder.setPosition(textWidth);
+
+ if(input.length() + leftIndent <= maxWidth)
+ return input;
+
+ int from = wrapFinder.toPreviousBoundary();
+ output.append(input.left(from));
+
+ while(true)
+ {
+ if((len - from) + leftIndent > maxWidth)
+ {
+ /* We need to line wrap. */
+ wrapFinder.setPosition(from + textWidth);
+ const int currentWidthPos = wrapFinder.toPreviousBoundary();
+
+ output.append(QLatin1Char('\n'));
+ output.append(indent);
+ output.append(input.mid(from, currentWidthPos - from).trimmed());
+ from += (currentWidthPos - from);
+ }
+ else
+ {
+ /* Append the remains. */
+ output.append(QLatin1Char('\n'));
+ output.append(indent);
+ output.append(input.mid(from).trimmed());
+ break;
+ }
+ }
+
+ return output;
+}
+
+/*!
+ Returns a list with the builtin options that the parser has
+ */
+QList<QApplicationArgument> QApplicationArgumentParserPrivate::builtinArguments()
+{
+ QList<QApplicationArgument> result;
+
+ result.append(QApplicationArgument(QLatin1String("help"),
+ QLatin1String("Displays this help.")));
+ result.append(QApplicationArgument(QLatin1String("version"),
+ QLatin1String("Displays version information.")));
+
+ result.append(QApplicationArgument(QLatin1String("-"),
+ QLatin1String("When appearing, any following options are not interpreted as switches.")));
+ return result;
+}
+
+/* TODO, I don't think we want this function in a public API. Add it first when there is a demand. */
+
+/*!
+ Creates a QApplicationArgumentParser that will parse the input in \a argc and \a argv.
+These arguments should be passed directly from the \c main() function, and the decoding
+of the input will be taken care of appropriately, depending on platform.
+
+ It is preferred to use the QStringList overload, in case the input is in the form of QStrings.
+ */
+QApplicationArgumentParser::QApplicationArgumentParser(int argc, char **argv) : d(new QApplicationArgumentParserPrivate(this, QApplicationArgumentParserPrivate::argumentsFromLocal(argc, argv)))
+{
+ Q_ASSERT_X(argv, Q_FUNC_INFO, "Argv cannot be null.");
+ Q_ASSERT_X(argc >= 1, Q_FUNC_INFO,
+ "argc must at least contain the application name. "
+ "Use the QStringList overload instead.");
+}
+
+/*!
+ \overload
+
+ Creates a QApplicationArgumentParser that will parse \a input. That is, instead of passing in \c argc
+ and \c argv, one can pass in a QStringList.
+
+ The caller guarantees that the first string in \a input is the name of the application.
+ */
+QApplicationArgumentParser::QApplicationArgumentParser(const QStringList &input) : d(new QApplicationArgumentParserPrivate(this, input))
+{
+ Q_ASSERT_X(input.count() >= 1, Q_FUNC_INFO,
+ "The input must at least contain the application name.");
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Returns the strings that the user specified when starting the application. The first string
+ in the list is always the application name.
+ */
+QStringList QApplicationArgumentParser::input() const
+{
+ Q_ASSERT_X(d->input.count() >= 1, Q_FUNC_INFO, "Internal error, this should always hold true");
+ return d->input;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Sets the arguments that the user actually used on the command line to \a arguments.
+ The parse() function should call this, such that the result afterwards can be inspected
+ with for instance has() or count().
+
+\sa usedArguments()
+*/
+void QApplicationArgumentParser::setUsedArguments(const QList<QPair<QApplicationArgument, QVariant> > &arguments)
+{
+ d->usedArguments = arguments;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Returns the arguments that the user used on the command line.
+
+\sa setUsedArguments()
+*/
+QList<QPair<QApplicationArgument, QVariant> > QApplicationArgumentParser::usedArguments() const
+{
+ return d->usedArguments;
+}
+
+/*!
+ Destructs this QApplicationArgumentParser instance.
+ */
+QApplicationArgumentParser::~QApplicationArgumentParser()
+{
+ delete d;
+}
+
+/*!
+ Adds \a argument to this parser.
+
+ This function is provided for convenience. It is equivalent to creating a QList
+ containing \a argument, append the existing arguments, and then call setDeclaredArguments() with the list.
+
+ \sa setDeclaredArguments()
+ */
+void QApplicationArgumentParser::addArgument(const QApplicationArgument &argument)
+{
+ if(argument.isNameless())
+ d->declaredNamelessArguments.append(argument);
+ else
+ d->declaredArguments.insert(argument.name(), argument);
+}
+
+/*!
+ Makes the parser recognize all arguments in \a arguments.
+
+ Any arguments previously set, are discarded.
+
+ \sa addArgument(), declaredArguments()
+ */
+void QApplicationArgumentParser::setDeclaredArguments(const QList<QApplicationArgument> &arguments)
+{
+ // TODO If we have a QHash internally, why not use it in the public API too?
+ const int len = arguments.count();
+
+ for(int i = 0; i < len; ++i)
+ d->declaredArguments.insert(arguments.at(i).name(), arguments.at(i));
+}
+
+/*!
+ Returns the arguments that this parser recognizes.
+
+ \sa addArgument(), setDeclaredArguments()
+ */
+QList<QApplicationArgument> QApplicationArgumentParser::declaredArguments() const
+{
+ return d->declaredArguments.values();
+}
+
+bool QApplicationArgumentParserPrivate::parseNamelessArguments(const QString &in)
+{
+ /* It's a nameless options, such as simply "value". */
+ const QApplicationArgument nameless(nextNamelessArgument());
+
+ const QVariant val(q_ptr->convertToValue(nameless, in));
+ if(val.isValid())
+ {
+ usedArguments.append(qMakePair(nameless, val));
+ return true;
+ }
+ else
+ return false; // TODO error msg?
+}
+
+/*!
+ Parses input() together with declaredArguments() and returns \c false if the caller
+ should exit immediately, which is the case of which an error was encountered or
+ help or the version was requested.
+
+ In the case of \c true was returned, valid arguments were supplied, and they can
+ be requested with functions like value(), values(), count() and has().
+
+ parse() must only be called once per QApplicationArgumentParser instance. The
+ second time it's called, the effects and return value are undefined.
+
+ \sa convertToValue(), typeToName()
+ */
+bool QApplicationArgumentParser::parse()
+{
+ const QChar sep(QLatin1Char('-'));
+ const int inputCount = d->input.count();
+
+ /* We skip the first entry, which is the application name. */
+ int i = 1;
+
+ for(; i < inputCount; ++i)
+ {
+ const QString &in = d->input.at(i);
+
+ /* We have a single '-', signalling that the succeeding are not options. */
+ if(in == sep)
+ {
+ ++i;
+
+ for(; i < inputCount; ++i)
+ {
+ if(!d->parseNamelessArguments(d->input.at(i)))
+ return false;
+ /* Process nameless options. Have code for this elsewhere, factor it out. */
+ }
+
+ break;
+ }
+
+ if(in.startsWith(sep)) /* It is "-name". */
+ {
+ const QString name(in.mid(1));
+
+ if(name == QLatin1String("help"))
+ {
+ setExitCode(Success);
+ d->displayHelp();
+ return false;
+ }
+ else if(name == QLatin1String("version"))
+ {
+ setExitCode(Success);
+ d->displayVersion();
+ return false;
+ }
+
+ if(!d->declaredArguments.contains(name))
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" is an unknown argument.").arg(name));
+
+ const QApplicationArgument &arg = d->declaredArguments.value(name);
+ const int argCount = d->count(arg) + 1;
+ const int max = arg.maximumOccurrence();
+
+ if(argCount > max && max != -1)
+ {
+ /* Let's tailor the message for a common case. */
+ if(max == 1)
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" can only be used once.").arg(name));
+ else
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" can only be used %2 times.").arg(name, QString::number(max)));
+ }
+
+ if(QApplicationArgumentParserPrivate::isSwitch(arg))
+ {
+ d->usedArguments.append(qMakePair(arg, QVariant()));
+ continue;
+ }
+ else
+ {
+ ++i;
+
+ if(i == inputCount)
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" must be followed by a value.").arg(name));
+
+ /* Okidoki, got a value, always something. Let's
+ * see if it validates. */
+ const QString &value = d->input.at(i);
+
+ const QVariant val(convertToValue(arg, value));
+ if(val.isValid())
+ {
+ d->usedArguments.append(qMakePair(arg, val));
+ continue;
+ }
+ else
+ return false; // TODO error msg?
+ }
+ }
+ else
+ {
+ if(!d->parseNamelessArguments(in))
+ return false;
+ }
+ }
+
+ /* Check that all arguments that have been declared as mandatory, are actually
+ * specified. */
+ const QList<QApplicationArgument> declaredArguments(d->declaredArguments.values() + d->declaredNamelessArguments);
+ const int len = declaredArguments.count();
+ for(int i = 0; i < len; ++i)
+ {
+ const QApplicationArgument &at = declaredArguments.at(i);
+ const int min = at.minimumOccurrence();
+ const int max = at.maximumOccurrence(); // TODO What about infinite? -1
+ if(min == 0)
+ continue;
+ else
+ {
+ const int usedLen = d->usedArguments.count();
+ int useCount = 0;
+
+ for(int u = 0; u < usedLen; ++u)
+ {
+ const QPair<QApplicationArgument, QVariant> &used = d->usedArguments.at(u);
+ if(used.first == at)
+ ++useCount;
+ }
+
+ const QString originalName(at.name());
+ const QString effectiveName(originalName.isEmpty() ? QLatin1Char('<') + typeToName(at) + QLatin1Char('>') : originalName);
+
+ if(useCount < min)
+ {
+ /* For nameless options, we use the type as the name. Looks better. */
+ return d->error(QApplicationArgumentParserPrivate::tr("%1 must occur at least %2 times, therefore %3 times is insufficient.", "The number is for %2.", min)
+ .arg(effectiveName, QString::number(min), QString::number(useCount)));
+ }
+ else if(useCount > max)
+ return d->error(QApplicationArgumentParserPrivate::tr("%1 can occur at most %2 times", "", max).arg(effectiveName, QString::number(max)));
+ }
+ }
+
+ d->exitCode = Success;
+ return true;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ parse() calls this function each time a value, that is \a input, on the command line needs to be
+ validated and subsequently converted to the type of \a argument. A descriptive error message will
+ be outputted if \a input cannot be converted to the required type.
+
+ The default implementation uses QVariant::canConvert() and QVariant::convert() for doing conversions.
+
+ QApplicationArgumentParser can be subclassed and this function subsequently overridden, to handle custom types.
+
+ If \a input isn't valid input for \a argument, this function returns a default constructed
+ QVariant.
+
+ \sa typeToName(), parse()
+ */
+QVariant QApplicationArgumentParser::convertToValue(const QApplicationArgument &argument,
+ const QString &input) const
+{
+ const int type = argument.type();
+
+ switch(type)
+ {
+ case QVariant::Bool:
+ {
+ if(input == QLatin1String("true") || input == QChar::fromLatin1('1'))
+ return QVariant(true);
+ else if(input == QLatin1String("false") || input == QChar::fromLatin1('0'))
+ return QVariant(false);
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ case QVariant::RegExp:
+ {
+ const QRegExp exp(input);
+
+ if(exp.isValid())
+ return QVariant(exp);
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ case QVariant::Url:
+ {
+ const QUrl result(QUrl::fromEncoded(input.toLatin1()));
+
+ if(result.isValid())
+ return QVariant(result);
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ default:
+ {
+ QVariant result(input);
+
+ if(QApplicationArgumentParserPrivate::isBuiltinVariant(type) &&
+ result.convert(QVariant::Type(type)))
+ return result;
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ }
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ convertToValue() calls this function when requiring a string for referring to \a type,
+ when generating user messages.
+
+ The implementation uses QVariant::typeToName() for most types, but special handles
+ some types, in order to let the message be better tailored for humans.
+
+ \sa convertToValue()
+ */
+QString QApplicationArgumentParser::typeToName(const QApplicationArgument &argument) const
+{
+ /* Personally I think nameForType() would be a better name but this is consistent
+ * with QVariant's function of the same name. */
+ const int type = argument.type();
+
+ switch(type)
+ {
+ case QVariant::RegExp:
+ return QApplicationArgumentParserPrivate::tr("regular expression");
+ case QVariant::Url:
+ return QLatin1String("URI");
+ case QVariant::String:
+ return QLatin1String("string");
+ default:
+ {
+ if(QApplicationArgumentParserPrivate::isBuiltinVariant(type))
+ return QString::fromLatin1(QVariant::typeToName(QVariant::Type(type)));
+ else
+ return QLatin1String(QVariant(type, static_cast<void *>(0)).typeName());
+ }
+ }
+}
+
+/*!
+ Returns the default value for \a argument. The default implementation returns
+ QApplicationArgument::defaultValue(), if \a argument has been added to this parser.
+
+ Overriding this function can be useful if creating the default value is resource
+ consuming, such as opening a file.
+ */
+QVariant QApplicationArgumentParser::defaultValue(const QApplicationArgument &argument) const
+{
+ return d->declaredArguments.value(argument.name()).defaultValue();
+}
+
+/*!
+ Returns the count of how many times \a argument was used on the command line.
+
+ \sa has()
+ */
+int QApplicationArgumentParser::count(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+ return d->count(argument);
+}
+
+/*!
+ Returns \c true if \a argument has been
+ specified one or more times on the command line, otherwise \a false.
+
+ \sa count()
+ */
+bool QApplicationArgumentParser::has(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+ return d->contains(argument);
+}
+
+/*!
+ // TODO docs
+
+ \sa values()
+ */
+QVariant QApplicationArgumentParser::value(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+
+ const int len = d->usedArguments.count();
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(d->usedArguments.at(i).first == argument)
+ return d->usedArguments.at(i).second;
+ }
+
+ return defaultValue(argument);
+}
+
+/*!
+ // TODO docs
+ \sa value()
+ */
+QVariantList QApplicationArgumentParser::values(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument),
+ Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+
+ const int len = d->usedArguments.count();
+
+ QVariantList result;
+ for(int i = 0; i < len; ++i)
+ {
+ if(d->usedArguments.at(i).first == argument)
+ result.append(d->usedArguments.at(i).second);
+ }
+
+ // TODO how do we handle default values?
+ return result;
+}
+
+/*!
+ After parse() has been called, this function returns a code that can be used to
+ exit \c main() with. It returns zero upon success or if help was requested, and
+ otherwise a value signalling failure.
+ */
+QApplicationArgumentParser::ExitCode QApplicationArgumentParser::exitCode() const
+{
+ return d->exitCode;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Makes exitCode() return \a code.
+ */
+void QApplicationArgumentParser::setExitCode(ExitCode code)
+{
+ d->exitCode = code;
+}
+
+/*!
+ Sets the application description to \a description.
+
+ The application description is a sentence or two used for help and version
+ messages, that briefly describes the application.
+
+ The default is the empty string.
+ */
+void QApplicationArgumentParser::setApplicationDescription(const QString &description)
+{
+ d->applicationDescription = description;
+}
+
+/*!
+ Sets the application version to \a version.
+
+ This string, which is arbitrary but typically is "1.0" or so, is used when
+ generating a version statement.
+*/
+void QApplicationArgumentParser::setApplicationVersion(const QString &version)
+{
+ d->applicationVersion = version;
+}
+
+/*!
+ Writes out \a message to \c stderr.
+ */
+void QApplicationArgumentParser::message(const QString &message) const
+{
+ d->errorMessage(message);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/xmlpatterns/qapplicationargumentparser_p.h b/tools/xmlpatterns/qapplicationargumentparser_p.h
new file mode 100644
index 0000000..f17a7ea
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargumentparser_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QApplicationArgumentParser_H
+#define QApplicationArgumentParser_H
+
+#include <QtCore/QVariant> /* Needed, because we can't forward declare QVariantList. */
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QApplicationArgument;
+class QApplicationArgumentParserPrivate;
+class QStringList;
+template<typename A, typename B> struct QPair;
+template<typename T> class QList;
+template<typename Value> class QList;
+
+class QApplicationArgumentParser
+{
+public:
+ enum ExitCode
+ {
+ Success = 0,
+ ParseError = 1
+ };
+
+ QApplicationArgumentParser(int argc, char **argv);
+ QApplicationArgumentParser(const QStringList &input);
+ virtual ~QApplicationArgumentParser();
+ void addArgument(const QApplicationArgument &argument);
+ void setDeclaredArguments(const QList<QApplicationArgument> &arguments);
+ QList<QApplicationArgument> declaredArguments() const;
+
+ int count(const QApplicationArgument &argument) const;
+ bool has(const QApplicationArgument &argument) const;
+
+ virtual bool parse();
+ ExitCode exitCode() const;
+ QVariant value(const QApplicationArgument &argument) const;
+ QVariantList values(const QApplicationArgument &argument) const;
+ void setApplicationDescription(const QString &description);
+ void setApplicationVersion(const QString &version);
+ virtual void message(const QString &message) const;
+
+protected:
+ void setExitCode(ExitCode code);
+ void setUsedArguments(const QList<QPair<QApplicationArgument, QVariant> > &arguments);
+ QList<QPair<QApplicationArgument, QVariant> > usedArguments() const;
+ QStringList input() const;
+ virtual QVariant convertToValue(const QApplicationArgument &argument,
+ const QString &value) const;
+ virtual QString typeToName(const QApplicationArgument &argument) const;
+ virtual QVariant defaultValue(const QApplicationArgument &argument) const;
+
+private:
+ friend class QApplicationArgumentParserPrivate;
+ QApplicationArgumentParserPrivate *d;
+ Q_DISABLE_COPY(QApplicationArgumentParser)
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
diff --git a/tools/xmlpatterns/xmlpatterns.pro b/tools/xmlpatterns/xmlpatterns.pro
new file mode 100644
index 0000000..8cd321c
--- /dev/null
+++ b/tools/xmlpatterns/xmlpatterns.pro
@@ -0,0 +1,28 @@
+TEMPLATE = app
+TARGET = xmlpatterns
+DESTDIR = ../../bin
+QT -= gui
+QT += xmlpatterns
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+
+# This ensures we get stderr and stdout on Windows.
+CONFIG += console
+
+# This ensures that this is a command-line program on OS X and not a GUI application.
+CONFIG -= app_bundle
+
+# Note that qcoloroutput.cpp and qcoloringmessagehandler.cpp are also used internally
+# in libQtXmlPatterns. See src/xmlpatterns/api/api.pri.
+SOURCES = main.cpp \
+ qapplicationargument.cpp \
+ qapplicationargumentparser.cpp
+
+
+HEADERS = main.h \
+ qapplicationargument.cpp \
+ qapplicationargumentparser.cpp
+
+symbian: TARGET.UID3 = 0xA000D7C9
+
diff --git a/tools/xmlpatternsvalidator/main.cpp b/tools/xmlpatternsvalidator/main.cpp
new file mode 100644
index 0000000..0b1555f
--- /dev/null
+++ b/tools/xmlpatternsvalidator/main.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "main.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+#include <QtXmlPatterns/QXmlSchema>
+#include <QtXmlPatterns/QXmlSchemaValidator>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ enum ExitCode
+ {
+ Valid = 0,
+ Invalid,
+ ParseError
+ };
+
+ enum ExecutionMode
+ {
+ InvalidMode,
+ SchemaOnlyMode,
+ InstanceOnlyMode,
+ SchemaAndInstanceMode
+ };
+
+ const QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationName(QLatin1String("xmlpatternsvalidator"));
+
+ QStringList arguments = QCoreApplication::arguments();
+ if (arguments.size() != 2 && arguments.size() != 3) {
+ qDebug() << QXmlPatternistCLI::tr("usage: xmlpatternsvalidator (<schema url> | <instance url> <schema url> | <instance url>)");
+ return ParseError;
+ }
+
+ // parse command line arguments
+ ExecutionMode mode = InvalidMode;
+
+ QUrl schemaUri;
+ QUrl instanceUri;
+
+ {
+ QUrl url = arguments[1];
+
+ if (url.isRelative())
+ url = QUrl::fromLocalFile(arguments[1]);
+
+ if (arguments.size() == 2) {
+ // either it is a schema or instance document
+
+ if (arguments[1].toLower().endsWith(QLatin1String(".xsd"))) {
+ schemaUri = url;
+ mode = SchemaOnlyMode;
+ } else {
+ // as we could validate all types of xml documents, don't check the extension here
+ instanceUri = url;
+ mode = InstanceOnlyMode;
+ }
+ } else if (arguments.size() == 3) {
+ instanceUri = url;
+ schemaUri = arguments[2];
+
+ if (schemaUri.isRelative())
+ schemaUri = QUrl::fromLocalFile(schemaUri.toString());
+
+ mode = SchemaAndInstanceMode;
+ }
+ }
+
+ // Validate schema
+ QXmlSchema schema;
+ if (InstanceOnlyMode != mode) {
+ schema.load(schemaUri);
+ if (!schema.isValid())
+ return Invalid;
+ }
+
+ if (SchemaOnlyMode == mode)
+ return Valid;
+
+ // Validate instance
+ QXmlSchemaValidator validator(schema);
+ if (validator.validate(instanceUri))
+ return Valid;
+
+ return Invalid;
+}
diff --git a/tools/xmlpatternsvalidator/main.h b/tools/xmlpatternsvalidator/main.h
new file mode 100644
index 0000000..78df377
--- /dev/null
+++ b/tools/xmlpatternsvalidator/main.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_main_h
+#define Patternist_main_h
+
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QXmlPatternistCLI
+{
+public:
+ Q_DECLARE_TR_FUNCTIONS(QXmlPatternistCLI)
+private:
+ inline QXmlPatternistCLI();
+ Q_DISABLE_COPY(QXmlPatternistCLI)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro b/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro
new file mode 100644
index 0000000..17fc465
--- /dev/null
+++ b/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+TARGET = xmlpatternsvalidator
+DESTDIR = ../../bin
+QT -= gui
+QT += xmlpatterns
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+
+# This ensures we get stderr and stdout on Windows.
+CONFIG += console
+
+# This ensures that this is a command-line program on OS X and not a GUI application.
+CONFIG -= app_bundle
+
+SOURCES = main.cpp
+HEADERS = main.h
+
+symbian: TARGET.UID3 = 0xA000D7CA