diff options
-rw-r--r-- | examples/network/dnslookup/dnslookup.cpp | 171 | ||||
-rw-r--r-- | examples/network/dnslookup/dnslookup.h | 20 | ||||
-rw-r--r-- | src/corelib/doc/qtcore.qdocconf | 3 | ||||
-rw-r--r-- | src/corelib/tools/qcommandlineparser.cpp | 72 |
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 */ |