QCommandLineParser: add --help-all, to show Qt options as well
Sample output at http://www.kdab.com/~dfaure/2019/help-all-example.txt Fixes: QTBUG-41802 Change-Id: I7a3350200761d41481fcb10ec4328e96e548d246 Reviewed-by: André Hartmann <aha_1980@gmx.de> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
parent
b75e6e00b7
commit
341c8b9cd0
|
|
@ -226,6 +226,13 @@ bool QCoreApplicationPrivate::checkInstance(const char *function)
|
|||
return b;
|
||||
}
|
||||
|
||||
void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
|
||||
{
|
||||
options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
|
||||
QStringLiteral("Activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block]. \"block\" makes the application wait for a connection."),
|
||||
QStringLiteral("value")));
|
||||
}
|
||||
|
||||
void QCoreApplicationPrivate::processCommandLineArguments()
|
||||
{
|
||||
int j = argc ? 1 : 0;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ private:
|
|||
#endif
|
||||
friend Q_CORE_EXPORT QString qAppName();
|
||||
friend class QClassFactory;
|
||||
friend class QCommandLineParserPrivate;
|
||||
};
|
||||
|
||||
#ifdef QT_NO_DEPRECATED
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
//
|
||||
|
||||
#include "QtCore/qcoreapplication.h"
|
||||
#include "QtCore/qcommandlineoption.h"
|
||||
#include "QtCore/qtranslator.h"
|
||||
#if QT_CONFIG(settings)
|
||||
#include "QtCore/qsettings.h"
|
||||
|
|
@ -104,6 +105,8 @@ public:
|
|||
|
||||
static bool checkInstance(const char *method);
|
||||
|
||||
virtual void addQtOptions(QList<QCommandLineOption> *options);
|
||||
|
||||
#ifndef QT_NO_QOBJECT
|
||||
bool sendThroughApplicationEventFilters(QObject *, QEvent *);
|
||||
static bool sendThroughObjectEventFilters(QObject *, QEvent *);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "qcommandlineparser.h"
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
#include <private/qcoreapplication_p.h>
|
||||
#include <qhash.h>
|
||||
#include <qvector.h>
|
||||
#include <qdebug.h>
|
||||
|
|
@ -70,11 +71,12 @@ public:
|
|||
bool parse(const QStringList &args);
|
||||
void checkParsed(const char *method);
|
||||
QStringList aliases(const QString &name) const;
|
||||
QString helpText() const;
|
||||
QString helpText(bool includeQtOptions) const;
|
||||
bool registerFoundOption(const QString &optionName);
|
||||
bool parseOptionValue(const QString &optionName, const QString &argument,
|
||||
QStringList::const_iterator *argumentIterator,
|
||||
QStringList::const_iterator argsEnd);
|
||||
Q_NORETURN void showHelp(int exitCode, bool includeQtOptions);
|
||||
|
||||
//! Error text set when parse() returns false
|
||||
QString errorText;
|
||||
|
|
@ -419,7 +421,9 @@ QCommandLineOption QCommandLineParser::addVersionOption()
|
|||
|
||||
/*!
|
||||
Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows)
|
||||
This option is handled automatically by QCommandLineParser.
|
||||
as well as an option \c{--help-all} to include Qt-specific options in the output.
|
||||
|
||||
These options are handled automatically by QCommandLineParser.
|
||||
|
||||
Remember to use setApplicationDescription to set the application description,
|
||||
which will be displayed when this option is used.
|
||||
|
|
@ -436,8 +440,10 @@ QCommandLineOption QCommandLineParser::addHelpOption()
|
|||
<< QStringLiteral("?")
|
||||
#endif
|
||||
<< QStringLiteral("h")
|
||||
<< QStringLiteral("help"), tr("Displays this help."));
|
||||
<< QStringLiteral("help"), tr("Displays help on commandline options."));
|
||||
addOption(opt);
|
||||
QCommandLineOption optHelpAll(QStringLiteral("help-all"), tr("Displays help including Qt specific options."));
|
||||
addOption(optHelpAll);
|
||||
d->builtinHelpOption = true;
|
||||
return opt;
|
||||
}
|
||||
|
|
@ -581,7 +587,8 @@ static void showParserMessage(const QString &message, MessageType type)
|
|||
In addition to parsing the options (like parse()), this function also handles the builtin
|
||||
options and handles errors.
|
||||
|
||||
The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called.
|
||||
The builtin options are \c{--version} if addVersionOption was called and
|
||||
\c{--help} / \c{--help-all} if addHelpOption was called.
|
||||
|
||||
When invoking one of these options, or when an error happens (for instance an unknown option was
|
||||
passed), the current process will then stop, using the exit() function.
|
||||
|
|
@ -600,7 +607,10 @@ void QCommandLineParser::process(const QStringList &arguments)
|
|||
showVersion();
|
||||
|
||||
if (d->builtinHelpOption && isSet(QStringLiteral("help")))
|
||||
showHelp(EXIT_SUCCESS);
|
||||
d->showHelp(EXIT_SUCCESS, false);
|
||||
|
||||
if (d->builtinHelpOption && isSet(QStringLiteral("help-all")))
|
||||
d->showHelp(EXIT_SUCCESS, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -1033,7 +1043,12 @@ Q_NORETURN void QCommandLineParser::showVersion()
|
|||
*/
|
||||
Q_NORETURN void QCommandLineParser::showHelp(int exitCode)
|
||||
{
|
||||
showParserMessage(d->helpText(), UsageMessage);
|
||||
d->showHelp(exitCode, false);
|
||||
}
|
||||
|
||||
Q_NORETURN void QCommandLineParserPrivate::showHelp(int exitCode, bool includeQtOptions)
|
||||
{
|
||||
showParserMessage(helpText(includeQtOptions), UsageMessage);
|
||||
qt_call_post_routines();
|
||||
::exit(exitCode);
|
||||
}
|
||||
|
|
@ -1045,7 +1060,7 @@ Q_NORETURN void QCommandLineParser::showHelp(int exitCode)
|
|||
*/
|
||||
QString QCommandLineParser::helpText() const
|
||||
{
|
||||
return d->helpText();
|
||||
return d->helpText(false);
|
||||
}
|
||||
|
||||
static QString wrapText(const QString &names, int longestOptionNameString, const QString &description)
|
||||
|
|
@ -1103,13 +1118,16 @@ static QString wrapText(const QString &names, int longestOptionNameString, const
|
|||
return text;
|
||||
}
|
||||
|
||||
QString QCommandLineParserPrivate::helpText() const
|
||||
QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const
|
||||
{
|
||||
const QLatin1Char nl('\n');
|
||||
QString text;
|
||||
QString usage;
|
||||
usage += QCoreApplication::instance()->arguments().constFirst(); // executable name
|
||||
if (!commandLineOptionList.isEmpty())
|
||||
QList<QCommandLineOption> options = commandLineOptionList;
|
||||
if (includeQtOptions)
|
||||
QCoreApplication::instance()->d_func()->addQtOptions(&options);
|
||||
if (!options.isEmpty())
|
||||
usage += QLatin1Char(' ') + QCommandLineParser::tr("[options]");
|
||||
for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions)
|
||||
usage += QLatin1Char(' ') + arg.syntax;
|
||||
|
|
@ -1117,12 +1135,12 @@ QString QCommandLineParserPrivate::helpText() const
|
|||
if (!description.isEmpty())
|
||||
text += description + nl;
|
||||
text += nl;
|
||||
if (!commandLineOptionList.isEmpty())
|
||||
if (!options.isEmpty())
|
||||
text += QCommandLineParser::tr("Options:") + nl;
|
||||
QStringList optionNameList;
|
||||
optionNameList.reserve(commandLineOptionList.size());
|
||||
optionNameList.reserve(options.size());
|
||||
int longestOptionNameString = 0;
|
||||
for (const QCommandLineOption &option : commandLineOptionList) {
|
||||
for (const QCommandLineOption &option : qAsConst(options)) {
|
||||
if (option.flags() & QCommandLineOption::HiddenFromHelp)
|
||||
continue;
|
||||
const QStringList optionNames = option.names();
|
||||
|
|
@ -1141,14 +1159,14 @@ QString QCommandLineParserPrivate::helpText() const
|
|||
}
|
||||
++longestOptionNameString;
|
||||
auto optionNameIterator = optionNameList.cbegin();
|
||||
for (const QCommandLineOption &option : commandLineOptionList) {
|
||||
for (const QCommandLineOption &option : qAsConst(options)) {
|
||||
if (option.flags() & QCommandLineOption::HiddenFromHelp)
|
||||
continue;
|
||||
text += wrapText(*optionNameIterator, longestOptionNameString, option.description());
|
||||
++optionNameIterator;
|
||||
}
|
||||
if (!positionalArgumentDefinitions.isEmpty()) {
|
||||
if (!commandLineOptionList.isEmpty())
|
||||
if (!options.isEmpty())
|
||||
text += nl;
|
||||
text += QCommandLineParser::tr("Arguments:") + nl;
|
||||
for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions)
|
||||
|
|
|
|||
|
|
@ -1306,6 +1306,58 @@ static void init_plugins(const QList<QByteArray> &pluginList)
|
|||
}
|
||||
}
|
||||
|
||||
void QGuiApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
|
||||
{
|
||||
QCoreApplicationPrivate::addQtOptions(options);
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
const QByteArray sessionType = qgetenv("XDG_SESSION_TYPE");
|
||||
const bool x11 = sessionType == "x11";
|
||||
// Technically the x11 aliases are only available if platformName is "xcb", but we can't know that here.
|
||||
#else
|
||||
const bool x11 = false;
|
||||
#endif
|
||||
|
||||
options->append(QCommandLineOption(QStringLiteral("platform"),
|
||||
QGuiApplication::tr("QPA plugin. See QGuiApplication documentation for available options for each plugin."), QStringLiteral("platformName[:options]")));
|
||||
options->append(QCommandLineOption(QStringLiteral("platformpluginpath"),
|
||||
QGuiApplication::tr("Path to the platform plugins."), QStringLiteral("path")));
|
||||
options->append(QCommandLineOption(QStringLiteral("platformtheme"),
|
||||
QGuiApplication::tr("Platform theme."), QStringLiteral("theme")));
|
||||
options->append(QCommandLineOption(QStringLiteral("plugin"),
|
||||
QGuiApplication::tr("Additional plugins to load, can be specified multiple times."), QStringLiteral("plugin")));
|
||||
options->append(QCommandLineOption(QStringLiteral("qwindowgeometry"),
|
||||
QGuiApplication::tr("Window geometry for the main window, using the X11-syntax, like 100x100+50+50."), QStringLiteral("geometry")));
|
||||
options->append(QCommandLineOption(QStringLiteral("qwindowicon"),
|
||||
QGuiApplication::tr("Default window icon."), QStringLiteral("icon")));
|
||||
options->append(QCommandLineOption(QStringLiteral("qwindowtitle"),
|
||||
QGuiApplication::tr("Title of the first window."), QStringLiteral("title")));
|
||||
options->append(QCommandLineOption(QStringLiteral("reverse"),
|
||||
QGuiApplication::tr("Sets the application's layout direction to Qt::RightToLeft (debugging helper).")));
|
||||
options->append(QCommandLineOption(QStringLiteral("session"),
|
||||
QGuiApplication::tr("Restores the application from an earlier session."), QStringLiteral("session")));
|
||||
|
||||
if (x11) {
|
||||
options->append(QCommandLineOption(QStringLiteral("display"),
|
||||
QGuiApplication::tr("Display name, overrides $DISPLAY."), QStringLiteral("display")));
|
||||
options->append(QCommandLineOption(QStringLiteral("name"),
|
||||
QGuiApplication::tr("Instance name according to ICCCM 4.1.2.5."), QStringLiteral("name")));
|
||||
options->append(QCommandLineOption(QStringLiteral("nograb"),
|
||||
QGuiApplication::tr("Disable mouse grabbing (useful in debuggers).")));
|
||||
options->append(QCommandLineOption(QStringLiteral("dograb"),
|
||||
QGuiApplication::tr("Force mouse grabbing (even when running in a debugger).")));
|
||||
options->append(QCommandLineOption(QStringLiteral("visual"),
|
||||
QGuiApplication::tr("ID of the X11 Visual to use."), QStringLiteral("id")));
|
||||
// Not using the "QStringList names" solution for those aliases, because it makes the first column too wide
|
||||
options->append(QCommandLineOption(QStringLiteral("geometry"),
|
||||
QGuiApplication::tr("Alias for --windowgeometry."), QStringLiteral("geometry")));
|
||||
options->append(QCommandLineOption(QStringLiteral("icon"),
|
||||
QGuiApplication::tr("Alias for --windowicon."), QStringLiteral("icon")));
|
||||
options->append(QCommandLineOption(QStringLiteral("title"),
|
||||
QGuiApplication::tr("Alias for --windowtitle."), QStringLiteral("title")));
|
||||
}
|
||||
}
|
||||
|
||||
void QGuiApplicationPrivate::createPlatformIntegration()
|
||||
{
|
||||
QHighDpiScaling::initHighDpiScaling();
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ public:
|
|||
virtual void notifyLayoutDirectionChange();
|
||||
virtual void notifyActiveWindowChange(QWindow *previous);
|
||||
|
||||
void addQtOptions(QList<QCommandLineOption> *options) override;
|
||||
virtual bool shouldQuit() override;
|
||||
|
||||
bool shouldQuitInternal(const QWindowList &processedWindows);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ private slots:
|
|||
void testHelpOption();
|
||||
void testQuoteEscaping();
|
||||
void testUnknownOption();
|
||||
void testHelpAll_data();
|
||||
void testHelpAll();
|
||||
};
|
||||
|
||||
static char *empty_argv[] = { 0 };
|
||||
|
|
@ -542,7 +544,8 @@ void tst_QCommandLineParser::testVersionOption()
|
|||
|
||||
static const char expectedOptionsHelp[] =
|
||||
"Options:\n"
|
||||
" -h, --help Displays this help.\n"
|
||||
" -h, --help Displays help on commandline options.\n"
|
||||
" --help-all Displays help including Qt specific options.\n"
|
||||
" -v, --version Displays version information.\n"
|
||||
" --load <url> Load file from URL.\n"
|
||||
" -o, --output <file> Set output file.\n"
|
||||
|
|
@ -576,8 +579,8 @@ void tst_QCommandLineParser::testHelpOption_data()
|
|||
" parsingMode The parsing mode to test.\n"
|
||||
" command The command to execute.\n");
|
||||
#ifdef Q_OS_WIN
|
||||
expectedOutput.replace(" -h, --help Displays this help.\n",
|
||||
" -?, -h, --help Displays this help.\n");
|
||||
expectedOutput.replace(" -h, --help Displays help on commandline options.\n",
|
||||
" -?, -h, --help Displays help on commandline options.\n");
|
||||
expectedOutput.replace("testhelper/", "testhelper\\");
|
||||
#endif
|
||||
|
||||
|
|
@ -625,8 +628,8 @@ void tst_QCommandLineParser::testHelpOption()
|
|||
"Arguments:\n"
|
||||
" resize Resize the object to a new size.\n";
|
||||
#ifdef Q_OS_WIN
|
||||
expectedResizeHelp.replace(" -h, --help Displays this help.\n",
|
||||
" -?, -h, --help Displays this help.\n");
|
||||
expectedResizeHelp.replace(" -h, --help Displays help on commandline options.\n",
|
||||
" -?, -h, --help Displays help on commandline options.\n");
|
||||
expectedResizeHelp.replace("testhelper/", "testhelper\\");
|
||||
#endif
|
||||
QCOMPARE(output, QString(expectedResizeHelp));
|
||||
|
|
@ -680,6 +683,60 @@ void tst_QCommandLineParser::testUnknownOption()
|
|||
#endif // QT_CONFIG(process)
|
||||
}
|
||||
|
||||
void tst_QCommandLineParser::testHelpAll_data()
|
||||
{
|
||||
QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
|
||||
QTest::addColumn<QString>("expectedHelpOutput");
|
||||
|
||||
QString expectedOutput = QString::fromLatin1(
|
||||
"Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n"
|
||||
"Test helper\n"
|
||||
"\n")
|
||||
+ QString::fromLatin1(expectedOptionsHelp) +
|
||||
QString::fromLatin1(
|
||||
" --qmljsdebugger <value> Activates the QML/JS debugger with a specified\n"
|
||||
" port. The value must be of format\n"
|
||||
" port:1234[,block]. \"block\" makes the application\n"
|
||||
" wait for a connection.\n"
|
||||
"\n"
|
||||
"Arguments:\n"
|
||||
" parsingMode The parsing mode to test.\n"
|
||||
" command The command to execute.\n");
|
||||
#ifdef Q_OS_WIN
|
||||
expectedOutput.replace(" -h, --help Displays help on commandline options.\n",
|
||||
" -?, -h, --help Displays help on commandline options.\n");
|
||||
expectedOutput.replace("testhelper/", "testhelper\\");
|
||||
#endif
|
||||
|
||||
QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << expectedOutput;
|
||||
QTest::newRow("long") << QCommandLineParser::ParseAsLongOptions << expectedOutput;
|
||||
}
|
||||
|
||||
void tst_QCommandLineParser::testHelpAll()
|
||||
{
|
||||
#if !QT_CONFIG(process)
|
||||
QSKIP("This test requires QProcess support");
|
||||
#else
|
||||
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
|
||||
QSKIP("Deploying executable applications to file system on Android not supported.");
|
||||
#endif
|
||||
|
||||
QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
|
||||
QFETCH(QString, expectedHelpOutput);
|
||||
QCoreApplication app(empty_argc, empty_argv);
|
||||
QProcess process;
|
||||
process.start("testhelper/qcommandlineparser_test_helper", QStringList() << QString::number(parsingMode) << "--help-all");
|
||||
QVERIFY(process.waitForFinished(5000));
|
||||
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
|
||||
QString output = process.readAll();
|
||||
#ifdef Q_OS_WIN
|
||||
output.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
|
||||
#endif
|
||||
QCOMPARE(output.split('\n'), expectedHelpOutput.split('\n')); // easier to debug than the next line, on failure
|
||||
QCOMPARE(output, expectedHelpOutput);
|
||||
#endif // QT_CONFIG(process)
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QCommandLineParser)
|
||||
#include "tst_qcommandlineparser.moc"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue