summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2014-03-11 09:35:35 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-15 10:44:41 +0100
commit51e5378113ac185ce9b3f64417416243050f6335 (patch)
treed99bbe1bf9f5c8359282b5aa6ce242a1a426e499
parent00fe7bd975be844a63d688a12d10a2e9611baf4a (diff)
Use QCommandLineParser in example dnslookup.
Show how use QCommandLineParser with additional parameter checking for custom options and positional arguments. Also explain how to display help in GUI applications. Change-Id: I03513e09b7dd5b150259593da0af2ef2a281cab2 Reviewed-by: David Faure <david.faure@kdab.com>
-rw-r--r--examples/network/dnslookup/dnslookup.cpp171
-rw-r--r--examples/network/dnslookup/dnslookup.h20
-rw-r--r--src/corelib/doc/qtcore.qdocconf3
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp72
4 files changed, 210 insertions, 56 deletions
diff --git a/examples/network/dnslookup/dnslookup.cpp b/examples/network/dnslookup/dnslookup.cpp
index 202a5f9580..003a3e3028 100644
--- a/examples/network/dnslookup/dnslookup.cpp
+++ b/examples/network/dnslookup/dnslookup.cpp
@@ -45,71 +45,114 @@
#include <QHostAddress>
#include <QStringList>
#include <QTimer>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
#include <stdio.h>
-static void usage() {
- printf("Qt DNS example - performs DNS lookups\n"
- "Usage: dnslookup [-t <type>] [-s nameserver] name\n\n");
+static int typeFromParameter(const QString &type)
+{
+ if (type == "a")
+ return QDnsLookup::A;
+ if (type == "aaaa")
+ return QDnsLookup::AAAA;
+ if (type == "any")
+ return QDnsLookup::ANY;
+ if (type == "cname")
+ return QDnsLookup::CNAME;
+ if (type == "mx")
+ return QDnsLookup::MX;
+ if (type == "ns")
+ return QDnsLookup::NS;
+ if (type == "ptr")
+ return QDnsLookup::PTR;
+ if (type == "srv")
+ return QDnsLookup::SRV;
+ if (type == "txt")
+ return QDnsLookup::TXT;
+ return -1;
}
-DnsManager::DnsManager()
+//! [0]
+
+enum CommandLineParseResult
{
- dns = new QDnsLookup(this);
- connect(dns, SIGNAL(finished()), this, SLOT(showResults()));
-}
+ CommandLineOk,
+ CommandLineError,
+ CommandLineVersionRequested,
+ CommandLineHelpRequested
+};
-void DnsManager::execute()
+CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query, QString *errorMessage)
{
- QStringList args = QCoreApplication::instance()->arguments();
- args.takeFirst();
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+ const QCommandLineOption nameServerOption("n", "The name server to use.", "nameserver");
+ parser.addOption(nameServerOption);
+ const QCommandLineOption typeOption("t", "The lookup type.", "type");
+ parser.addOption(typeOption);
+ parser.addPositionalArgument("name", "The name to look up.");
+ const QCommandLineOption helpOption = parser.addHelpOption();
+ const QCommandLineOption versionOption = parser.addVersionOption();
+
+ if (!parser.parse(QCoreApplication::arguments())) {
+ *errorMessage = parser.errorText();
+ return CommandLineError;
+ }
- // lookup type
- dns->setType(QDnsLookup::A);
- if (args.size() > 1 && args.first() == "-t") {
- args.takeFirst();
- const QString type = args.takeFirst().toLower();
- if (type == "a")
- dns->setType(QDnsLookup::A);
- else if (type == "aaaa")
- dns->setType(QDnsLookup::AAAA);
- else if (type == "any")
- dns->setType(QDnsLookup::ANY);
- else if (type == "cname")
- dns->setType(QDnsLookup::CNAME);
- else if (type == "mx")
- dns->setType(QDnsLookup::MX);
- else if (type == "ns")
- dns->setType(QDnsLookup::NS);
- else if (type == "ptr")
- dns->setType(QDnsLookup::PTR);
- else if (type == "srv")
- dns->setType(QDnsLookup::SRV);
- else if (type == "txt")
- dns->setType(QDnsLookup::TXT);
- else {
- printf("Bad record type: %s\n", qPrintable(type));
- QCoreApplication::instance()->quit();
- return;
+ if (parser.isSet(versionOption))
+ return CommandLineVersionRequested;
+
+ if (parser.isSet(helpOption))
+ return CommandLineHelpRequested;
+
+ if (parser.isSet(nameServerOption)) {
+ const QString nameserver = parser.value(nameServerOption);
+ query->nameServer = QHostAddress(nameserver);
+ if (query->nameServer.isNull() || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
+ *errorMessage = "Bad nameserver address: " + nameserver;
+ return CommandLineError;
}
}
- if (args.size() > 1 && args.first() == "-s") {
- args.takeFirst();
- const QString ns = args.takeFirst();
- QHostAddress nameserver(ns);
- if (nameserver.isNull() || nameserver.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
- printf("Bad nameserver address: %s\n", qPrintable(ns));
- QCoreApplication::instance()->quit();
- return;
+
+ if (parser.isSet(typeOption)) {
+ const QString typeParameter = parser.value(typeOption);
+ const int type = typeFromParameter(typeParameter.toLower());
+ if (type < 0) {
+ *errorMessage = "Bad record type: " + typeParameter;
+ return CommandLineError;
}
- dns->setNameserver(nameserver);
+ query->type = static_cast<QDnsLookup::Type>(type);
}
- if (args.isEmpty()) {
- usage();
- QCoreApplication::instance()->quit();
- return;
+
+ const QStringList positionalArguments = parser.positionalArguments();
+ if (positionalArguments.isEmpty()) {
+ *errorMessage = "Argument 'name' missing.";
+ return CommandLineError;
+ }
+ if (positionalArguments.size() > 1) {
+ *errorMessage = "Several 'name' arguments specified.";
+ return CommandLineError;
}
- dns->setName(args.takeFirst());
+ query->name = positionalArguments.first();
+
+ return CommandLineOk;
+}
+
+//! [0]
+
+DnsManager::DnsManager()
+{
+ dns = new QDnsLookup(this);
+ connect(dns, SIGNAL(finished()), this, SLOT(showResults()));
+}
+
+void DnsManager::execute()
+{
+ // lookup type
+ dns->setType(query.type);
+ if (!query.nameServer.isNull())
+ dns->setNameserver(query.nameServer);
+ dns->setName(query.name);
dns->lookup();
}
@@ -159,7 +202,33 @@ int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
+//! [1]
+ QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+ QCoreApplication::setApplicationName(QCoreApplication::translate("QDnsLookupExample", "DNS Lookup Example"));
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QCoreApplication::translate("QDnsLookupExample", "An example demonstrating the class QDnsLookup."));
+ DnsQuery query;
+ QString errorMessage;
+ switch (parseCommandLine(parser, &query, &errorMessage)) {
+ case CommandLineOk:
+ break;
+ case CommandLineError:
+ fputs(qPrintable(errorMessage), stderr);
+ fputs("\n\n", stderr);
+ fputs(qPrintable(parser.helpText()), stderr);
+ return 1;
+ case CommandLineVersionRequested:
+ printf("%s %s\n", qPrintable(QCoreApplication::applicationName()),
+ qPrintable(QCoreApplication::applicationVersion()));
+ return 0;
+ case CommandLineHelpRequested:
+ parser.showHelp();
+ Q_UNREACHABLE();
+ }
+//! [1]
+
DnsManager manager;
+ manager.setQuery(query);
QTimer::singleShot(0, &manager, SLOT(execute()));
return app.exec();
diff --git a/examples/network/dnslookup/dnslookup.h b/examples/network/dnslookup/dnslookup.h
index d76756bad0..4d0232be8a 100644
--- a/examples/network/dnslookup/dnslookup.h
+++ b/examples/network/dnslookup/dnslookup.h
@@ -38,11 +38,21 @@
**
****************************************************************************/
-#include <QObject>
+#include <QDnsLookup>
+#include <QHostAddress>
-QT_BEGIN_NAMESPACE
-class QDnsLookup;
-QT_END_NAMESPACE
+//! [0]
+
+struct DnsQuery
+{
+ DnsQuery() : type(QDnsLookup::A) {}
+
+ QDnsLookup::Type type;
+ QHostAddress nameServer;
+ QString name;
+};
+
+//! [0]
class DnsManager : public QObject
{
@@ -50,6 +60,7 @@ class DnsManager : public QObject
public:
DnsManager();
+ void setQuery(const DnsQuery &q) { query = q; }
public slots:
void execute();
@@ -57,5 +68,6 @@ public slots:
private:
QDnsLookup *dns;
+ DnsQuery query;
};
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index 18fdfb18f3..2ad24d33b1 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -37,7 +37,8 @@ exampledirs += \
snippets \
../../../examples/threads/ \
../../../examples/tools/ \
- ../../../examples/json/
+ ../../../examples/json/ \
+ ../../../examples/network/dnslookup
imagedirs += images
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index c860b4d155..505ab5f46d 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -187,6 +187,78 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
QCoreApplication::arguments() before QCommandLineParser defines the \c{profile}
option and parses the command line.
+ \section2 How to Use QCommandLineParser in Complex Applications
+
+ In practice, additional error checking needs to be performed on the positional
+ arguments and option values. For example, ranges of numbers should be checked.
+
+ It is then advisable to introduce a function to do the command line parsing
+ which takes a struct or class receiving the option values returning an
+ enumeration representing the result. The dnslookup example of the QtNetwork
+ module illustrates this:
+
+ \snippet dnslookup.h 0
+
+ \snippet dnslookup.cpp 0
+
+ In the main function, help should be printed to the standard output if the help option
+ was passed and the application should return the exit code 0.
+
+ If an error was detected, the error message should be printed to the standard
+ error output and the application should return an exit code other than 0.
+
+ \snippet dnslookup.cpp 1
+
+ A special case to consider here are GUI applications on Windows and mobile
+ platforms. These applications may not use the standard output or error channels
+ since the output is either discarded or not accessible.
+
+ For such GUI applications, it is recommended to display help texts and error messages
+ using a QMessageBox. To preserve the formatting of the help text, rich text
+ with \c <pre> elements should be used:
+
+ \code
+
+ switch (parseCommandLine(parser, &query, &errorMessage)) {
+ case CommandLineOk:
+ break;
+ case CommandLineError:
+#ifdef Q_OS_WIN
+ QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
+ "<html><head/><body><h2>" + errorMessage + "</h2><pre>"
+ + parser.helpText() + "</pre></body></html>");
+#else
+ fputs(qPrintable(errorMessage), stderr);
+ fputs("\n\n", stderr);
+ fputs(qPrintable(parser.helpText()), stderr);
+#endif
+ return 1;
+ case CommandLineVersionRequested:
+#ifdef Q_OS_WIN
+ QMessageBox::information(0, QGuiApplication::applicationDisplayName(),
+ QGuiApplication::applicationDisplayName() + ' '
+ + QCoreApplication::applicationVersion());
+#else
+ printf("%s %s\n", QGuiApplication::applicationDisplayName(),
+ qPrintable(QCoreApplication::applicationVersion()));
+#endif
+ return 0;
+ case CommandLineHelpRequested:
+#ifdef Q_OS_WIN
+ QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
+ "<html><head/><body><pre>"
+ + parser.helpText() + "</pre></body></html>");
+ return 0;
+#else
+ parser.showHelp();
+ Q_UNREACHABLE();
+#endif
+ }
+ \endcode
+
+ However, this does not apply to the dnslookup example, because it is a
+ console application.
+
\sa QCommandLineOption, QCoreApplication
*/