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>
This commit is contained in:
parent
00fe7bd975
commit
51e5378113
@ -45,14 +45,101 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
//! [0]
|
||||
|
||||
enum CommandLineParseResult
|
||||
{
|
||||
CommandLineOk,
|
||||
CommandLineError,
|
||||
CommandLineVersionRequested,
|
||||
CommandLineHelpRequested
|
||||
};
|
||||
|
||||
CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query, QString *errorMessage)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 (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;
|
||||
}
|
||||
query->type = static_cast<QDnsLookup::Type>(type);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
query->name = positionalArguments.first();
|
||||
|
||||
return CommandLineOk;
|
||||
}
|
||||
|
||||
//! [0]
|
||||
|
||||
DnsManager::DnsManager()
|
||||
{
|
||||
dns = new QDnsLookup(this);
|
||||
@ -61,55 +148,11 @@ DnsManager::DnsManager()
|
||||
|
||||
void DnsManager::execute()
|
||||
{
|
||||
QStringList args = QCoreApplication::instance()->arguments();
|
||||
args.takeFirst();
|
||||
|
||||
// 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 (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;
|
||||
}
|
||||
dns->setNameserver(nameserver);
|
||||
}
|
||||
if (args.isEmpty()) {
|
||||
usage();
|
||||
QCoreApplication::instance()->quit();
|
||||
return;
|
||||
}
|
||||
dns->setName(args.takeFirst());
|
||||
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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -37,7 +37,8 @@ exampledirs += \
|
||||
snippets \
|
||||
../../../examples/threads/ \
|
||||
../../../examples/tools/ \
|
||||
../../../examples/json/
|
||||
../../../examples/json/ \
|
||||
../../../examples/network/dnslookup
|
||||
|
||||
imagedirs += images
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user