Don't use the QRegExp methods that modify the object
[profile/ivi/qtxmlpatterns.git] / tools / xmlpatterns / qapplicationargumentparser.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtDebug>
43 #include <QTextBoundaryFinder>
44 #include <QCoreApplication>
45 #include <QHash>
46 #include <QPair>
47 #include <QStringList>
48 #include <QTextStream>
49 #include <QUrl>
50
51 #include "qapplicationargument_p.h"
52
53 #include "qapplicationargumentparser_p.h"
54
55 QT_BEGIN_NAMESPACE
56
57 /*!
58  \class QApplicationArgumentParser
59  \brief The QApplicationArgumentParser class parses the command
60         line arguments for an application.
61  \reentrant
62  \internal
63  \since 4.4
64
65  QApplicationArgumentParser simplifies writing command line applications by taking care of:
66
67  \list
68     \li Generating help and version arguments
69     \li Taking care of converting arguments to QVariant types, since each argument
70        has a type: QApplicationArgument::type()
71     \li Validates the command line such that the user operates on well-defined input. For instance,
72        that the argument is a valid integer if that is the case, that an argument does not
73        occur more times than allowed, and so on.
74     \li Allows customization through sub-classing.
75  \endlist
76
77  The user declares what arguments that can be given to the application with QApplicationArgument. Provided
78  with that information, QApplicationArgumentParser takes care of parsing the actual
79  command line, appropriately flag errors, generate help messages, and provide
80  convenient access to the values of the arguments.
81
82  The way to use it is to create a set of QApplicationArgument by ones choosing, call
83  addArgument() for each, and subsequently call parse(). If parse() returns \c false,
84  the caller should exit and return exitCode().
85
86  If parse() returns \c true the command line was successfully parsed, its
87  values are well-defined, and they can be spectated with count(),
88  has(), value() and values().
89
90  \snippet doc/src/snippets/code/tools_patternist_qapplicationargumentparser.cpp 0
91
92  For arguments without a name(such as filename passed to the \c ls utility on Linux) add a
93  QApplicationArgument that does not have a name. The minimum and maximum occurrences will be
94  respected as usual and the type applies too.
95
96  QApplicationArgumentParser always has two options builtin: \c version and \c help.
97
98  \section1 Changing Parsing Convention
99
100  QApplicationArgumentParser by default parses the command line in the style
101  of Qt's utilities, where arguments are preceded by a single dash, and identified
102  by a single name. However, in some cases it might be of interest to parse
103  another style, such as the well-established UNIX \c getopt convention(\c -l
104  and \c --long).
105
106  This can be achieved by sub-classing QApplicationArgumentParser and reimplementing
107  parse(). It would do the following:
108
109  \list
110     \li Call input() to retrieve the strings the user specified on the command line.
111     \li Call declaredArguments() to retrieve the arguments that the implementor has
112        decided can be specified.
113     \li Parse and validate the input. Salt and pepper as per taste.
114     \li If an error occurred, call setExitCode() and return \c false.
115     \li Otherwise, call setExitCode(Success), provide access to the
116        arguments by calling setUsedArguments(), and return \c true. If a
117        help message was requested, call setExitCode(Success) and return \c false.
118  \endlist
119
120  \sa QApplicationArgument, QCoreApplication
121 */
122 class QApplicationArgumentParserPrivate
123 {
124     Q_DECLARE_TR_FUNCTIONS(QApplicationArgumentParserPrivate)
125 public:
126     // TODO Isn't it like ten times better with QHash<QApplicationArgument, QList<QVariant> >?
127     // TODO test QApplicationArgument::nameless()
128     typedef QList<QPair<QApplicationArgument, QVariant> > UsedList;
129
130     /*!
131      We initialize exitCode to ParseError such that we consciously flag success.
132      */
133     inline QApplicationArgumentParserPrivate(QApplicationArgumentParser *const master,
134                                              const QStringList &aInput) : exitCode(QApplicationArgumentParser::ParseError)
135                                                                         , input(aInput)
136                                                                         , q_ptr(master)
137     {
138         Q_ASSERT(!aInput.isEmpty());
139     }
140
141     QApplicationArgument nextNamelessArgument() const;
142     static QStringList argumentsFromLocal(const int argc, const char *const *const argv);
143
144     bool error(const QString &message);
145     static bool errorMessage(const QString &message);
146     static inline bool isSwitch(const QApplicationArgument &arg);
147     static inline QVariant conversionError(const QString &typeName,
148                                            const QString &input);
149     int count(const QApplicationArgument &arg) const;
150     bool contains(const QApplicationArgument &arg) const;
151     static inline bool isBuiltinVariant(const int type);
152     void displayVersion() const;
153     void displayHelp() const;
154     void parseNameless();
155     bool parseNamelessArguments(const QString &in);
156
157     QApplicationArgumentParser::ExitCode    exitCode;
158     const QStringList                       input;
159
160     /*!
161       Since the QString is QApplicationArgument::name() anyway, why
162       not use a QSet?
163      */
164     QHash<QString, QApplicationArgument>    declaredArguments;
165
166     QList<QApplicationArgument>             declaredNamelessArguments;
167
168     UsedList                                usedArguments;
169     QString                                 applicationDescription;
170     QString                                 applicationVersion;
171
172 private:
173     QApplicationArgumentParser *const       q_ptr;
174     Q_DECLARE_PUBLIC(QApplicationArgumentParser)
175
176     static QString lineWrap(const QString &input,
177                             const int leftIndent,
178                             const int width);
179     static QList<QApplicationArgument> builtinArguments();
180 };
181
182 QApplicationArgument QApplicationArgumentParserPrivate::nextNamelessArgument() const
183 {
184     /* Count how many nameless arguments we have so far. */
185     int count = 0;
186
187     for(int i = 0; i < usedArguments.count(); ++i)
188     {
189         if(usedArguments.at(i).first.isNameless())
190             ++count;
191     }
192
193     /* TODO this doesn't work for arguments that have more than one
194      * mandatory value(e.g nameless ones), since several values should
195      * then only count for one argument. */
196     for(int i = 0; i < declaredNamelessArguments.count(); ++i)
197     {
198         if(count)
199         {
200             /* Skip the ones we already have processed. */
201             --count;
202             continue;
203         }
204
205         if(declaredNamelessArguments.at(i).isNameless())
206             return declaredNamelessArguments.at(i);
207     }
208
209     return QApplicationArgument();
210 }
211
212 int QApplicationArgumentParserPrivate::count(const QApplicationArgument &arg) const
213 {
214     const int len = usedArguments.count();
215     int count = 0;
216
217     for(int i = 0; i < len; ++i)
218     {
219         if(usedArguments.at(i).first == arg)
220             ++count;
221     }
222
223     return count;
224 }
225
226 /*!
227  Returns \c true if \a arg has appeared on the command line, not whether it has been declared.
228  */
229 bool QApplicationArgumentParserPrivate::contains(const QApplicationArgument &arg) const
230 {
231     const int len = usedArguments.count();
232
233     for(int i = 0; i < len; ++i)
234     {
235         if(usedArguments.at(i).first == arg)
236             return true;
237     }
238
239     return false;
240 }
241
242 /*!
243  Returns always \c false.
244  */
245 bool QApplicationArgumentParserPrivate::error(const QString &message)
246 {
247     exitCode = QApplicationArgumentParser::ParseError;
248     errorMessage(message);
249     return errorMessage(tr("Pass -help for information about the command line."));
250 }
251
252 /*!
253  Returns always \c false.
254  */
255 bool QApplicationArgumentParserPrivate::errorMessage(const QString &message)
256 {
257     QTextStream out(stderr, QIODevice::WriteOnly);
258     out << message << endl;
259     return false;
260 }
261
262 /*!
263   \internal
264   Determines whether \a arg carries a value or is on/off.
265  */
266 bool QApplicationArgumentParserPrivate::isSwitch(const QApplicationArgument &arg)
267 {
268     return arg.type() == QVariant::Invalid;
269 }
270
271 QVariant QApplicationArgumentParserPrivate::conversionError(const QString &typeName,
272                                                             const QString &input)
273 {
274     errorMessage(tr("Cannot convert %1 to type %2.").arg(input, typeName));
275     return QVariant();
276 }
277
278 bool QApplicationArgumentParserPrivate::isBuiltinVariant(const int type)
279 {
280     return type < int(QVariant::UserType);
281 }
282
283 /*!
284   TODO Temporary, replace with a function in QCoreApplication.
285 */
286 QStringList QApplicationArgumentParserPrivate::argumentsFromLocal(const int argc, const char *const *const argv)
287 {
288     Q_ASSERT(argc >= 1);
289     Q_ASSERT(argv);
290     QStringList result;
291
292     for(int i = 0; i < argc; ++i)
293         result.append(QString::fromLocal8Bit(argv[i]));
294
295     return result;
296 }
297
298 void QApplicationArgumentParserPrivate::displayVersion() const
299 {
300     QTextStream out(stderr);
301
302     out << tr("%1 version %2 using Qt %3").arg(QCoreApplication::applicationName(), applicationVersion, QString::fromAscii(qVersion()))
303         << endl;
304 }
305
306 /*!
307  \internal
308  \relates QApplicationArgument
309
310  qLess() functor for QApplicationArgument that considers the name.
311  */
312 template<>
313 class qLess <QApplicationArgument>
314 {
315 public:
316     inline bool operator()(const QApplicationArgument &o1,
317                            const QApplicationArgument &o2) const
318     {
319         return o1.name().compare(o2.name()) < 0;
320     }
321 };
322
323 void QApplicationArgumentParserPrivate::displayHelp() const
324 {
325     enum Constants
326     {
327         /**
328          * When we want to line wrap, 80 minus a couple of characters. This should
329          * be suitable for vt100 compatible terminals.
330          */
331         LineWrapAt = 78,
332
333         /**
334          * The initial "  -" for each option.
335          */
336         IndentPadding = 3,
337
338         /**
339          * Pad for the brackets and space we use when we have a type.
340          */
341         ValueArgumentPadding = 4
342     };
343
344     QList<QApplicationArgument> args(declaredArguments.values());
345     args += builtinArguments();
346
347     /* Sort them, such that we get the nameless options at the end, and it
348      * generally looks tidy. */
349     qSort(args);
350
351     /* This is the basic approach:
352      * Switches:
353      *  -name description
354      * Value arguments:
355      *  -name <name-of-value-type> description
356      *
357      * Nameless arguments
358      *  name <type> description
359      *
360      * It all line-wraps at OutputWidth and the description is indented,
361      * where the highest indent is the length of the name plus length of the name
362      * of the type. */
363
364     /* First we find the name with the largest width. */
365     int maxWidth = 0;
366
367     QList<QApplicationArgument> nameless(declaredNamelessArguments);
368     qSort(nameless);
369
370     /* Note, here the nameless arguments appear last, but are sorted
371      * with themselves. */
372     QList<QApplicationArgument> allArgs(args + nameless);
373     const int allArgsCount = allArgs.count();
374
375     for(int i = 0; i < allArgsCount; ++i)
376     {
377         const QApplicationArgument &at = allArgs.at(i);
378         const int nameLength = at.name().length();
379         const QString typeName(q_ptr->typeToName(at));
380         const int typeNameLength = typeName.length();
381         const int padding = at.type() == QVariant::Invalid ? 0 : ValueArgumentPadding;
382         maxWidth = qMax(maxWidth, nameLength + typeNameLength + padding);
383     }
384
385     QTextStream out(stderr);
386     out << endl
387         << QString(IndentPadding, QLatin1Char(' '))
388         << QCoreApplication::applicationName()
389         << QLatin1String(" -- ")
390         << applicationDescription
391         << endl;
392     // TODO synopsis
393
394     /* One extra so we get some space between the overview and the options. */
395     out << endl;
396
397     const int indentWidth = maxWidth + 3;
398
399     /* Ok, print them out. */
400     for(int i = 0; i < allArgsCount; ++i)
401     {
402         const QApplicationArgument &at = allArgs.at(i);
403         /* "  -name ". Indent a bit first, inspired by Qt's moc. */
404         const QString &name = at.name();
405         QString prolog(QLatin1String("  "));
406        
407         /* We have a special case for the single dash. */
408         if(name == QChar::fromLatin1('-'))
409             prolog.append(name);
410         else
411         {
412             if(!at.isNameless())
413                 prolog.append(QLatin1Char('-'));
414
415              prolog.append(name + QLatin1Char(' '));
416         }
417
418         if(at.type() != QVariant::Invalid)
419         {
420             /* It's not a switch, it has a value. */
421
422             /* Do we have a default value? If so, the argument is optional. */
423             const QString typeName(q_ptr->typeToName(at));
424
425             if(at.defaultValue().isValid())
426                 prolog.append(QLatin1Char('[') + typeName + QLatin1Char(']'));
427             else
428                 prolog.append(QLatin1Char('<') + typeName + QLatin1Char('>'));
429             // TODO Don't we want to display the default value?
430             
431             prolog.append(QLatin1Char(' '));
432         }
433
434         prolog = prolog.leftJustified(indentWidth);
435
436         out << prolog
437             << lineWrap(at.description(), indentWidth, LineWrapAt)
438             << endl;
439     }
440 }
441
442 /*!
443  Line wraps \a input and indents each line with \a leftIndent spaces, such that
444  the width does not go beyond \a maxWidth.
445
446  The addition of line endings is accounted for by the caller.
447
448  With QTextBoundaryFinder our line wrapping is relatively fancy, since it
449  does it the Unicode-way.
450  */
451 QString QApplicationArgumentParserPrivate::lineWrap(const QString &input,
452                                                     const int leftIndent,
453                                                     const int maxWidth)
454 {
455     const QString indent(QString(leftIndent, QLatin1Char(' ')));
456     const int len = input.length();
457     const int textWidth = maxWidth - leftIndent;
458
459     QString output;
460     QTextBoundaryFinder wrapFinder(QTextBoundaryFinder::Line, input);
461     wrapFinder.setPosition(textWidth);
462
463     if(input.length() + leftIndent <= maxWidth)
464         return input;
465
466     int from = wrapFinder.toPreviousBoundary();
467     output.append(input.left(from));
468
469     while(true)
470     {
471         if((len - from) + leftIndent > maxWidth)
472         {
473             /* We need to line wrap. */
474             wrapFinder.setPosition(from + textWidth);
475             const int currentWidthPos = wrapFinder.toPreviousBoundary();
476
477             output.append(QLatin1Char('\n'));
478             output.append(indent);
479             output.append(input.mid(from, currentWidthPos - from).trimmed());
480             from += (currentWidthPos - from);
481         }
482         else
483         {
484             /* Append the remains.  */
485             output.append(QLatin1Char('\n'));
486             output.append(indent);
487             output.append(input.mid(from).trimmed());
488             break;
489         }
490     }
491
492     return output;
493 }
494
495 /*!
496  Returns a list with the builtin options that the parser has
497  */
498 QList<QApplicationArgument> QApplicationArgumentParserPrivate::builtinArguments()
499 {
500     QList<QApplicationArgument> result;
501
502     result.append(QApplicationArgument(QLatin1String("help"),
503                                        QLatin1String("Displays this help.")));
504     result.append(QApplicationArgument(QLatin1String("version"),
505                                        QLatin1String("Displays version information.")));
506     
507     result.append(QApplicationArgument(QLatin1String("-"),
508                                        QLatin1String("When appearing, any following options are not interpreted as switches.")));
509     return result;
510 }
511
512 /* TODO, I don't think we want this function in a public API. Add it first when there is a demand. */
513
514 /*!
515  Creates a QApplicationArgumentParser that will parse the input in \a argc and \a argv.
516 These arguments should be passed directly from the \c main() function, and the decoding
517 of the input will be taken care of appropriately, depending on platform.
518
519  It is preferred to use the QStringList overload, in case the input is in the form of QStrings.
520  */
521 QApplicationArgumentParser::QApplicationArgumentParser(int argc, char **argv) : d(new QApplicationArgumentParserPrivate(this, QApplicationArgumentParserPrivate::argumentsFromLocal(argc, argv)))
522 {
523     Q_ASSERT_X(argv, Q_FUNC_INFO, "Argv cannot be null.");
524     Q_ASSERT_X(argc >= 1, Q_FUNC_INFO,
525                "argc must at least contain the application name. "
526                "Use the QStringList overload instead.");
527 }
528
529 /*!
530  \overload
531
532  Creates a QApplicationArgumentParser that will parse \a input. That is, instead of passing in \c argc
533  and \c argv, one can pass in a QStringList.
534
535  The caller guarantees that the first string in \a input is the name of the application.
536  */
537 QApplicationArgumentParser::QApplicationArgumentParser(const QStringList &input) : d(new QApplicationArgumentParserPrivate(this, input))
538 {
539     Q_ASSERT_X(input.count() >= 1, Q_FUNC_INFO,
540                "The input must at least contain the application name.");
541 }
542
543 /*!
544  This function is only of interest when subclassing.
545
546  Returns the strings that the user specified when starting the application. The first string
547  in the list is always the application name.
548  */
549 QStringList QApplicationArgumentParser::input() const
550 {
551     Q_ASSERT_X(d->input.count() >= 1, Q_FUNC_INFO, "Internal error, this should always hold true");
552     return d->input;
553 }
554
555 /*!
556  This function is only of interest when subclassing.
557
558  Sets the arguments that the user actually used on the command line to \a arguments.
559  The parse() function should call this, such that the result afterwards can be inspected
560  with for instance has() or count().
561
562 \sa usedArguments()
563 */
564 void QApplicationArgumentParser::setUsedArguments(const QList<QPair<QApplicationArgument, QVariant> > &arguments)
565 {
566     d->usedArguments = arguments;
567 }
568
569 /*!
570  This function is only of interest when subclassing.
571
572  Returns the arguments that the user used on the command line.
573
574 \sa setUsedArguments()
575 */
576 QList<QPair<QApplicationArgument, QVariant> > QApplicationArgumentParser::usedArguments() const
577 {
578     return d->usedArguments;
579 }
580
581 /*!
582   Destructs this QApplicationArgumentParser instance.
583  */
584 QApplicationArgumentParser::~QApplicationArgumentParser()
585 {
586     delete d;
587 }
588
589 /*!
590   Adds \a argument to this parser.
591
592   This function is provided for convenience. It is equivalent to creating a QList
593   containing \a argument, append the existing arguments, and then call setDeclaredArguments() with the list.
594
595   \sa setDeclaredArguments()
596  */
597 void QApplicationArgumentParser::addArgument(const QApplicationArgument &argument)
598 {
599     if(argument.isNameless())
600         d->declaredNamelessArguments.append(argument);
601     else
602         d->declaredArguments.insert(argument.name(), argument);
603 }
604
605 /*!
606  Makes the parser recognize all arguments in \a arguments.
607
608  Any arguments previously set, are discarded.
609
610  \sa addArgument(), declaredArguments()
611  */
612 void QApplicationArgumentParser::setDeclaredArguments(const QList<QApplicationArgument> &arguments)
613 {
614     // TODO If we have a QHash internally, why not use it in the public API too?
615     const int len = arguments.count();
616
617     for(int i = 0; i < len; ++i)
618         d->declaredArguments.insert(arguments.at(i).name(), arguments.at(i));
619 }
620
621 /*!
622  Returns the arguments that this parser recognizes.
623
624  \sa addArgument(), setDeclaredArguments()
625  */
626 QList<QApplicationArgument> QApplicationArgumentParser::declaredArguments() const
627 {
628     return d->declaredArguments.values();
629 }
630
631 bool QApplicationArgumentParserPrivate::parseNamelessArguments(const QString &in)
632 {
633     /* It's a nameless options, such as simply "value". */
634     const QApplicationArgument nameless(nextNamelessArgument());
635
636     const QVariant val(q_ptr->convertToValue(nameless, in));
637     if(val.isValid())
638     {
639         usedArguments.append(qMakePair(nameless, val));
640         return true;
641     }
642     else
643         return false; // TODO error msg?
644 }
645
646 /*!
647  Parses input() together with declaredArguments() and returns \c false if the caller 
648  should exit immediately, which is the case of which an error was encountered or
649  help or the version was requested.
650
651  In the case of \c true was returned, valid arguments were supplied, and they can
652  be requested with functions like value(), values(), count() and has().
653
654  parse() must only be called once per QApplicationArgumentParser instance. The
655  second time it's called, the effects and return value are undefined.
656
657  \sa convertToValue(), typeToName()
658  */
659 bool QApplicationArgumentParser::parse()
660 {
661     const QChar sep(QLatin1Char('-'));
662     const int inputCount = d->input.count();
663
664     /* We skip the first entry, which is the application name. */
665     int i = 1;
666
667     for(; i < inputCount; ++i)
668     {
669         const QString &in = d->input.at(i);
670
671         /* We have a single '-', signalling that the succeeding are not options. */
672         if(in == sep)
673         {
674             ++i;
675
676             for(; i < inputCount; ++i)
677             {
678                 if(!d->parseNamelessArguments(d->input.at(i)))
679                     return false;
680                 /* Process nameless options. Have code for this elsewhere, factor it out. */
681             }
682
683             break;
684         }
685
686         if(in.startsWith(sep)) /* It is "-name". */
687         {
688             const QString name(in.mid(1));
689
690             if(name == QLatin1String("help"))
691             {
692                 setExitCode(Success);
693                 d->displayHelp();
694                 return false;
695             }
696             else if(name == QLatin1String("version"))
697             {
698                 setExitCode(Success);
699                 d->displayVersion();
700                 return false;
701             }
702
703             if(!d->declaredArguments.contains(name))
704                 return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" is an unknown argument.").arg(name));
705
706             const QApplicationArgument &arg = d->declaredArguments.value(name);
707             const int argCount = d->count(arg) + 1;
708             const int max = arg.maximumOccurrence();
709
710             if(argCount > max && max != -1)
711             {
712                 /* Let's tailor the message for a common case. */
713                 if(max == 1)
714                     return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" can only be used once.").arg(name));
715                 else
716                     return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" can only be used %2 times.").arg(name, QString::number(max)));
717             }
718
719             if(QApplicationArgumentParserPrivate::isSwitch(arg))
720             {
721                 d->usedArguments.append(qMakePair(arg, QVariant()));
722                 continue;
723             }
724             else
725             {
726                 ++i;
727
728                 if(i == inputCount)
729                     return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" must be followed by a value.").arg(name));
730
731                 /* Okidoki, got a value, always something. Let's
732                  * see if it validates. */
733                 const QString &value = d->input.at(i);
734
735                 const QVariant val(convertToValue(arg, value));
736                 if(val.isValid())
737                 {
738                     d->usedArguments.append(qMakePair(arg, val));
739                     continue;
740                 }
741                 else
742                     return false; // TODO error msg?
743             }
744         }
745         else
746         {
747             if(!d->parseNamelessArguments(in))
748                 return false;
749         }
750     }
751
752     /* Check that all arguments that have been declared as mandatory, are actually
753      * specified. */
754     const QList<QApplicationArgument> declaredArguments(d->declaredArguments.values() + d->declaredNamelessArguments);
755     const int len = declaredArguments.count();
756     for(int i = 0; i < len; ++i)
757     {
758         const QApplicationArgument &at = declaredArguments.at(i);
759         const int min = at.minimumOccurrence();
760         const int max = at.maximumOccurrence(); // TODO What about infinite? -1
761         if(min == 0)
762             continue;
763         else
764         {
765             const int usedLen = d->usedArguments.count();
766             int useCount = 0;
767
768             for(int u = 0; u < usedLen; ++u)
769             {
770                 const QPair<QApplicationArgument, QVariant> &used = d->usedArguments.at(u);
771                 if(used.first == at)
772                     ++useCount;
773             }
774
775             const QString originalName(at.name());
776             const QString effectiveName(originalName.isEmpty() ? QLatin1Char('<') + typeToName(at) + QLatin1Char('>') : originalName);
777
778             if(useCount < min)
779             {
780                 /* For nameless options, we use the type as the name. Looks better. */
781                 return d->error(QApplicationArgumentParserPrivate::tr("%1 must occur at least %2 times, therefore %3 times is insufficient.", "The number is for %2.", min)
782                                                                       .arg(effectiveName, QString::number(min), QString::number(useCount)));
783             }
784             else if(useCount > max)
785                 return d->error(QApplicationArgumentParserPrivate::tr("%1 can occur at most %2 times", "", max).arg(effectiveName, QString::number(max)));
786         }
787     }
788
789     d->exitCode = Success;
790     return true;
791 }
792
793 /*!
794  This function is only of interest when subclassing.
795
796  parse() calls this function each time a value, that is \a input, on the command line needs to be
797  validated and subsequently converted to the type of \a argument. A descriptive error message will
798  be outputted if \a input cannot be converted to the required type.
799
800  The default implementation uses QVariant::canConvert() and QVariant::convert() for doing conversions.
801
802  QApplicationArgumentParser can be subclassed and this function subsequently overridden, to handle custom types.
803
804  If \a input isn't valid input for \a argument, this function returns a default constructed
805  QVariant.
806
807  \sa typeToName(), parse()
808  */
809 QVariant QApplicationArgumentParser::convertToValue(const QApplicationArgument &argument,
810                                                     const QString &input) const
811 {
812     const int type = argument.type();
813
814     switch(type)
815     {
816         case QVariant::Bool:
817         {
818             if(input == QLatin1String("true") || input == QChar::fromLatin1('1'))
819                 return QVariant(true);
820             else if(input == QLatin1String("false") || input == QChar::fromLatin1('0'))
821                 return QVariant(false);
822             else
823                 return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
824         }
825         case QVariant::RegExp:
826         {
827             QRegExp exp(input);
828
829             if(exp.isValid())
830                 return QVariant(exp);
831             else
832                 return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
833         }
834         case QVariant::Url:
835         {
836             const QUrl result(input);
837
838             if(result.isValid())
839                 return QVariant(result);
840             else
841                 return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
842         }
843         default:
844         {
845             QVariant result(input);
846
847             if(QApplicationArgumentParserPrivate::isBuiltinVariant(type) &&
848                result.convert(QVariant::Type(type)))
849                 return result;
850             else
851                 return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
852         }
853     }
854 }
855
856 /*!
857  This function is only of interest when subclassing.
858
859   convertToValue() calls this function when requiring a string for referring to \a type,
860   when generating user messages.
861
862   The implementation uses QVariant::typeToName() for most types, but special handles
863   some types, in order to let the message be better tailored for humans.
864
865  \sa convertToValue()
866  */
867 QString QApplicationArgumentParser::typeToName(const QApplicationArgument &argument) const
868 {
869     /* Personally I think nameForType() would be a better name but this is consistent
870      * with QVariant's function of the same name. */
871     const int type = argument.type();
872
873     switch(type)
874     {
875         case QVariant::RegExp:
876             return QApplicationArgumentParserPrivate::tr("regular expression");
877         case QVariant::Url:
878             return QLatin1String("URI");
879         case QVariant::String:
880             return QLatin1String("string");
881         default:
882         {
883             if(QApplicationArgumentParserPrivate::isBuiltinVariant(type))
884                 return QString::fromLatin1(QVariant::typeToName(QVariant::Type(type)));
885             else
886                 return QLatin1String(QVariant(type, static_cast<void *>(0)).typeName());
887         }
888     }
889 }
890
891 /*!
892  Returns the default value for \a argument. The default implementation returns
893  QApplicationArgument::defaultValue(), if \a argument has been added to this parser.
894
895  Overriding this function can be useful if creating the default value is resource
896  consuming, such as opening a file.
897  */
898 QVariant QApplicationArgumentParser::defaultValue(const QApplicationArgument &argument) const
899 {
900     return d->declaredArguments.value(argument.name()).defaultValue();
901 }
902
903 /*!
904  Returns the count of how many times \a argument was used on the command line.
905
906  \sa has()
907  */
908 int QApplicationArgumentParser::count(const QApplicationArgument &argument) const
909 {
910     Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
911                d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
912                "The argument isn't known to the parser. Has addArgument() been called?");
913     return d->count(argument);
914 }
915
916 /*!
917  Returns \c true if \a argument has been
918  specified one or more times on the command line, otherwise \a false.
919
920  \sa count()
921  */
922 bool QApplicationArgumentParser::has(const QApplicationArgument &argument) const
923 {
924     Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
925                d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
926                "The argument isn't known to the parser. Has addArgument() been called?");
927     return d->contains(argument);
928 }
929
930 /*!
931   // TODO docs
932
933  \sa values()
934  */
935 QVariant QApplicationArgumentParser::value(const QApplicationArgument &argument) const
936 {
937     Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
938                d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
939                "The argument isn't known to the parser. Has addArgument() been called?");
940
941     const int len = d->usedArguments.count();
942
943     for(int i = 0; i < len; ++i)
944     {
945         if(d->usedArguments.at(i).first == argument)
946             return d->usedArguments.at(i).second;
947     }
948
949     return defaultValue(argument);
950 }
951
952 /*!
953   // TODO docs
954  \sa value()
955  */
956 QVariantList QApplicationArgumentParser::values(const QApplicationArgument &argument) const
957 {
958     Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
959                d->declaredNamelessArguments.contains(argument),
960                Q_FUNC_INFO,
961                "The argument isn't known to the parser. Has addArgument() been called?");
962
963     const int len = d->usedArguments.count();
964
965     QVariantList result;
966     for(int i = 0; i < len; ++i)
967     {
968         if(d->usedArguments.at(i).first == argument)
969             result.append(d->usedArguments.at(i).second);
970     }
971
972     // TODO how do we handle default values?
973     return result;
974 }
975
976 /*!
977  After parse() has been called, this function returns a code that can be used to
978  exit \c main() with. It returns zero upon success or if help was requested, and
979  otherwise a value signalling failure.
980  */
981 QApplicationArgumentParser::ExitCode QApplicationArgumentParser::exitCode() const
982 {
983     return d->exitCode;
984 }
985
986 /*!
987  This function is only of interest when subclassing.
988
989  Makes exitCode() return \a code.
990  */
991 void QApplicationArgumentParser::setExitCode(ExitCode code)
992 {
993     d->exitCode = code;
994 }
995
996 /*!
997  Sets the application description to \a description.
998
999  The application description is a sentence or two used for help and version
1000  messages, that briefly describes the application.
1001
1002  The default is the empty string.
1003  */
1004 void QApplicationArgumentParser::setApplicationDescription(const QString &description)
1005 {
1006     d->applicationDescription = description;
1007 }
1008
1009 /*!
1010  Sets the application version to \a version.
1011
1012  This string, which is arbitrary but typically is "1.0" or so, is used when
1013  generating a version statement.
1014 */
1015 void QApplicationArgumentParser::setApplicationVersion(const QString &version)
1016 {
1017     d->applicationVersion = version;
1018 }
1019
1020 /*!
1021  Writes out \a message to \c stderr.
1022  */
1023 void QApplicationArgumentParser::message(const QString &message) const
1024 {
1025     d->errorMessage(message);
1026 }
1027
1028 QT_END_NAMESPACE