4444
4545#include < QQmlApplicationEngine>
4646#include < QQmlComponent>
47+ #include < QCommandLineOption>
48+ #include < QCommandLineParser>
4749#include < QDir>
4850#include < QFile>
4951#include < QFileInfo>
@@ -288,8 +290,6 @@ void quietMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, const Q
288290 }
289291}
290292
291-
292- // ### Should command line arguments have translations? Qt creator doesn't, so maybe it's not worth it.
293293enum QmlApplicationType {
294294 QmlApplicationTypeUnknown
295295 , QmlApplicationTypeCore
@@ -317,45 +317,6 @@ void printVersion()
317317 exit (0 );
318318}
319319
320- void printUsage ()
321- {
322- printf (" Usage: qml [options] [files] [-- args]\n " );
323- printf (" \n " );
324- printf (" Any unknown argument before '--' will be treated as a QML file to be loaded.\n " );
325- printf (" Any number of QML files can be loaded. They will share the same engine.\n " );
326- printf (" 'gui' application type is only available if the QtGui module is available.\n " );
327- printf (" 'widget' application type is only available if the QtWidgets module is available.\n " );
328- printf (" \n " );
329- printf (" General Options:\n " );
330- printf (" \t -h, -help..................... Print this usage information and exit.\n " );
331- printf (" \t -v, -version.................. Print the version information and exit.\n " );
332- #ifdef QT_GUI_LIB
333- #ifndef QT_WIDGETS_LIB
334- printf (" \t -apptype [core|gui] .......... Select which application class to use. Default is gui.\n " );
335- #else
336- printf (" \t -apptype [core|gui|widget] ... Select which application class to use. Default is gui.\n " );
337- #endif // QT_WIDGETS_LIB
338- #endif // QT_GUI_LIB
339- printf (" \t -quiet ....................... Suppress all output.\n " );
340- printf (" \t -I [path] .................... Prepend the given path to the import paths.\n " );
341- printf (" \t -f [file] .................... Load the given file as a QML file.\n " );
342- printf (" \t -config [file] ............... Load the given file as the configuration file.\n " );
343- printf (" \t -- ........................... Arguments after this one are ignored by the launcher, but may be used within the QML application.\n " );
344- printf (" \t GL options:\n " );
345- printf (" \t -desktop.......................Force use of desktop GL (AA_UseDesktopOpenGL)\n " );
346- printf (" \t -gles..........................Force use of GLES (AA_UseOpenGLES)\n " );
347- printf (" \t -software......................Force use of software rendering (AA_UseOpenGLES)\n " );
348- printf (" \t -scaling.......................Enable High DPI scaling (AA_EnableHighDpiScaling)\n " );
349- printf (" \t -no-scaling....................Disable High DPI scaling (AA_DisableHighDpiScaling)\n " );
350- printf (" \t Debugging options:\n " );
351- printf (" \t -verbose ..................... Print information about what qml is doing, like specific file urls being loaded.\n " );
352- printf (" \t -translation [file] .......... Load the given file as the translations file.\n " );
353- printf (" \t -dummy-data [directory] ...... Load QML files from the given directory as context properties.\n " );
354- printf (" \t -slow-animations ............. Run all animations in slow motion.\n " );
355- printf (" \t -fixed-animations ............ Run animations off animation tick rather than wall time.\n " );
356- exit (0 );
357- }
358-
359320void noFilesGiven ()
360321{
361322 if (!quietMode)
@@ -368,7 +329,7 @@ void getAppFlags(int &argc, char **argv)
368329{
369330#ifdef QT_GUI_LIB
370331 for (int i=0 ; i<argc; i++) {
371- if (!strcmp (argv[i], " -apptype" )) { // Must be done before application, as it selects application
332+ if (!strcmp (argv[i], " -- apptype" ) || ! strcmp (argv[i], " -a " ) || ! strcmp (argv[i], " -apptype " )) {
372333 applicationType = QmlApplicationTypeUnknown;
373334 if (i+1 < argc) {
374335 if (!strcmp (argv[i+1 ], " core" ))
@@ -380,15 +341,6 @@ void getAppFlags(int &argc, char **argv)
380341 applicationType = QmlApplicationTypeWidget;
381342#endif // QT_WIDGETS_LIB
382343 }
383-
384- if (applicationType == QmlApplicationTypeUnknown) {
385- #ifndef QT_WIDGETS_LIB
386- printf (" -apptype must be followed by one of the following: core gui\n " );
387- #else
388- printf (" -apptype must be followed by one of the following: core gui widget\n " );
389- #endif // QT_WIDGETS_LIB
390- printUsage ();
391- }
392344 for (int j=i; j<argc-2 ; j++)
393345 argv[j] = argv[j+2 ];
394346 argc -= 2 ;
@@ -442,9 +394,6 @@ int main(int argc, char *argv[])
442394 getAppFlags (argc, argv);
443395 QCoreApplication *app = nullptr ;
444396 switch (applicationType) {
445- case QmlApplicationTypeCore:
446- app = new QCoreApplication (argc, argv);
447- break ;
448397#ifdef QT_GUI_LIB
449398 case QmlApplicationTypeGui:
450399 app = new LoaderApplication (argc, argv);
@@ -456,8 +405,10 @@ int main(int argc, char *argv[])
456405 break ;
457406#endif // QT_WIDGETS_LIB
458407#endif // QT_GUI_LIB
459- default :
460- Q_ASSERT_X (false , Q_FUNC_INFO, " impossible case" );
408+ case QmlApplicationTypeCore:
409+ Q_FALLTHROUGH ();
410+ default : // QmlApplicationTypeUnknown: not allowed, but we'll exit after checking apptypeOption below
411+ app = new QCoreApplication (argc, argv);
461412 break ;
462413 }
463414
@@ -475,68 +426,125 @@ int main(int argc, char *argv[])
475426 QString dummyDir;
476427
477428 // Handle main arguments
478- const QStringList argList = app->arguments ();
479- for (int i = 1 ; i < argList.count (); i++) {
480- const QString &arg = argList[i];
481- if (arg == QLatin1String (" -quiet" ))
482- quietMode = true ;
483- else if (arg == QLatin1String (" -v" ) || arg == QLatin1String (" -version" ))
484- printVersion ();
485- else if (arg == QLatin1String (" -h" ) || arg == QLatin1String (" -help" ))
486- printUsage ();
487- else if (arg == QLatin1String (" --" ))
488- break ;
489- else if (arg == QLatin1String (" -verbose" ))
490- verboseMode = true ;
429+ QCommandLineParser parser;
430+ parser.setSingleDashWordOptionMode (QCommandLineParser::ParseAsLongOptions);
431+ parser.setOptionsAfterPositionalArgumentsMode (QCommandLineParser::ParseAsPositionalArguments);
432+ const QCommandLineOption helpOption = parser.addHelpOption ();
433+ const QCommandLineOption versionOption = parser.addVersionOption ();
434+ #ifdef QT_GUI_LIB
435+ QCommandLineOption apptypeOption (QStringList () << QStringLiteral (" a" ) << QStringLiteral (" apptype" ),
436+ QCoreApplication::translate (" main" , " Select which application class to use. Default is gui." ),
437+ #ifdef QT_WIDGETS_LIB
438+ QStringLiteral (" core|gui|widget" ));
439+ #else
440+ QStringLiteral (" core|gui" ));
441+ #endif // QT_WIDGETS_LIB
442+ parser.addOption (apptypeOption); // Just for the help text... we've already handled this argument above
443+ #endif // QT_GUI_LIB
444+ QCommandLineOption importOption (QStringLiteral (" I" ),
445+ QCoreApplication::translate (" main" , " Prepend the given path to the import paths." ), QStringLiteral (" path" ));
446+ parser.addOption (importOption);
447+ QCommandLineOption qmlFileOption (QStringLiteral (" f" ),
448+ QCoreApplication::translate (" main" , " Load the given file as a QML file." ), QStringLiteral (" file" ));
449+ parser.addOption (qmlFileOption);
450+ QCommandLineOption configOption (QStringList () << QStringLiteral (" c" ) << QStringLiteral (" config" ),
451+ QCoreApplication::translate (" main" , " Load the given file as the configuration file." ), QStringLiteral (" file" ));
452+ parser.addOption (configOption);
453+ QCommandLineOption translationOption (QStringLiteral (" translation" ),
454+ QCoreApplication::translate (" main" , " Load the given file as the translations file." ), QStringLiteral (" file" ));
455+ parser.addOption (translationOption);
456+ QCommandLineOption dummyDataOption (QStringLiteral (" dummy-data" ),
457+ QCoreApplication::translate (" main" , " Load QML files from the given directory as context properties." ), QStringLiteral (" file" ));
458+ parser.addOption (dummyDataOption);
459+ // OpenGL options
460+ QCommandLineOption glDesktopOption (QStringLiteral (" desktop" ),
461+ QCoreApplication::translate (" main" , " Force use of desktop OpenGL (AA_UseDesktopOpenGL)." ));
462+ parser.addOption (glDesktopOption);
463+ QCommandLineOption glEsOption (QStringLiteral (" gles" ),
464+ QCoreApplication::translate (" main" , " Force use of GLES (AA_UseOpenGLES)." ));
465+ parser.addOption (glEsOption);
466+ QCommandLineOption glSoftwareOption (QStringLiteral (" software" ),
467+ QCoreApplication::translate (" main" , " Force use of software rendering (AA_UseSoftwareOpenGL)." ));
468+ parser.addOption (glSoftwareOption);
469+ QCommandLineOption scalingOption (QStringLiteral (" scaling" ),
470+ QCoreApplication::translate (" main" , " Enable High DPI scaling (AA_EnableHighDpiScaling)." ));
471+ parser.addOption (scalingOption);
472+ QCommandLineOption noScalingOption (QStringLiteral (" no-scaling" ),
473+ QCoreApplication::translate (" main" , " Disable High DPI scaling (AA_DisableHighDpiScaling)." ));
474+ parser.addOption (noScalingOption);
475+ // Debugging and verbosity options
476+ QCommandLineOption quietOption (QStringLiteral (" quiet" ),
477+ QCoreApplication::translate (" main" , " Suppress all output." ));
478+ parser.addOption (quietOption);
479+ QCommandLineOption verboseOption (QStringLiteral (" verbose" ),
480+ QCoreApplication::translate (" main" , " Print information about what qml is doing, like specific file URLs being loaded." ));
481+ parser.addOption (verboseOption);
482+ QCommandLineOption slowAnimationsOption (QStringLiteral (" slow-animations" ),
483+ QCoreApplication::translate (" main" , " Run all animations in slow motion." ));
484+ parser.addOption (slowAnimationsOption);
485+ QCommandLineOption fixedAnimationsOption (QStringLiteral (" fixed-animations" ),
486+ QCoreApplication::translate (" main" , " Run animations off animation tick rather than wall time." ));
487+ parser.addOption (fixedAnimationsOption);
488+ // Positional arguments
489+ parser.addPositionalArgument (" files" ,
490+ QCoreApplication::translate (" main" , " Any number of QML files can be loaded. They will share the same engine." ), " [files...]" );
491+ parser.addPositionalArgument (" args" ,
492+ QCoreApplication::translate (" main" , " Arguments after '--' are ignored, but passed through to the application.arguments variable in QML." ), " [-- args...]" );
493+
494+ if (!parser.parse (QCoreApplication::arguments ())) {
495+ qWarning () << parser.errorText ();
496+ exit (1 );
497+ }
498+ if (parser.isSet (versionOption))
499+ parser.showVersion ();
500+ if (parser.isSet (helpOption))
501+ parser.showHelp ();
502+ if (applicationType == QmlApplicationTypeUnknown) {
503+ #ifdef QT_WIDGETS_LIB
504+ qWarning () << QCoreApplication::translate (" main" , " --apptype must be followed by one of the following: core gui widget\n " );
505+ #else
506+ qWarning () << QCoreApplication::translate (" main" , " --apptype must be followed by one of the following: core gui\n " );
507+ #endif // QT_WIDGETS_LIB
508+ parser.showHelp ();
509+ }
510+ if (parser.isSet (verboseOption))
511+ verboseMode = true ;
512+ if (parser.isSet (quietOption)) {
513+ quietMode = true ;
514+ verboseMode = false ;
515+ }
491516#if QT_CONFIG(qml_animation)
492- else if (arg == QLatin1String ( " -slow-animations " ))
493- QUnifiedTimer::instance ()->setSlowModeEnabled (true );
494- else if (arg == QLatin1String ( " -fixed-animations " ))
495- QUnifiedTimer::instance ()->setConsistentTiming (true );
517+ if (parser. isSet (slowAnimationsOption ))
518+ QUnifiedTimer::instance ()->setSlowModeEnabled (true );
519+ if (parser. isSet (fixedAnimationsOption ))
520+ QUnifiedTimer::instance ()->setConsistentTiming (true );
496521#endif
497- else if (arg == QLatin1String (" -I" )) {
498- if (i+1 == argList.count ())
499- continue ; // Invalid usage, but just ignore it
500- e.addImportPath (argList[i+1 ]);
501- i++;
502- } else if (arg == QLatin1String (" -f" )) {
503- if (i+1 == argList.count ())
504- continue ; // Invalid usage, but just ignore it
505- files << argList[i+1 ];
506- i++;
507- } else if (arg == QLatin1String (" -config" )){
508- if (i+1 == argList.count ())
509- continue ; // Invalid usage, but just ignore it
510- confFile = argList[i+1 ];
511- i++;
512- } else if (arg == QLatin1String (" -translation" )){
513- if (i+1 == argList.count ())
514- continue ; // Invalid usage, but just ignore it
515- translationFile = argList[i+1 ];
516- i++;
517- } else if (arg == QLatin1String (" -dummy-data" )){
518- if (i+1 == argList.count ())
519- continue ; // Invalid usage, but just ignore it
520- dummyDir = argList[i+1 ];
521- i++;
522- } else if (arg == QLatin1String (" -gles" )) {
523- QCoreApplication::setAttribute (Qt::AA_UseOpenGLES);
524- } else if (arg == QLatin1String (" -software" )) {
525- QCoreApplication::setAttribute (Qt::AA_UseSoftwareOpenGL);
526- } else if (arg == QLatin1String (" -desktop" )) {
527- QCoreApplication::setAttribute (Qt::AA_UseDesktopOpenGL);
528- } else if (arg == QLatin1String (" -scaling" )) {
529- QCoreApplication::setAttribute (Qt::AA_EnableHighDpiScaling);
530- } else if (arg == QLatin1String (" -no-scaling" )) {
531- QCoreApplication::setAttribute (Qt::AA_DisableHighDpiScaling);
532- } else {
533- files << arg;
534- }
522+ if (parser.isSet (glEsOption))
523+ QCoreApplication::setAttribute (Qt::AA_UseOpenGLES);
524+ if (parser.isSet (glSoftwareOption))
525+ QCoreApplication::setAttribute (Qt::AA_UseSoftwareOpenGL);
526+ if (parser.isSet (glDesktopOption))
527+ QCoreApplication::setAttribute (Qt::AA_UseDesktopOpenGL);
528+ if (parser.isSet (scalingOption))
529+ QCoreApplication::setAttribute (Qt::AA_EnableHighDpiScaling);
530+ if (parser.isSet (noScalingOption))
531+ QCoreApplication::setAttribute (Qt::AA_DisableHighDpiScaling);
532+ for (const QString &importPath : parser.values (importOption))
533+ e.addImportPath (importPath);
534+ files << parser.values (qmlFileOption);
535+ if (parser.isSet (configOption))
536+ confFile = parser.value (configOption);
537+ if (parser.isSet (translationOption))
538+ translationFile = parser.value (translationOption);
539+ if (parser.isSet (dummyDataOption))
540+ dummyDir = parser.value (dummyDataOption);
541+ for (QString posArg : parser.positionalArguments ()) {
542+ if (posArg == QLatin1String (" --" ))
543+ break ;
544+ else
545+ files << posArg;
535546 }
536547
537- if (quietMode && verboseMode)
538- verboseMode = false ;
539-
540548#if QT_CONFIG(translation)
541549 // Need to be installed before QQmlApplicationEngine's automatic translation loading
542550 // (qt_ translations are loaded there)
0 commit comments