aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qml/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/qml/main.cpp')
-rw-r--r--tools/qml/main.cpp370
1 files changed, 198 insertions, 172 deletions
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 166c6aabdf..1e367d91bf 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -44,9 +44,12 @@
#include <QQmlApplicationEngine>
#include <QQmlComponent>
+#include <QCommandLineOption>
+#include <QCommandLineParser>
#include <QDir>
#include <QFile>
#include <QFileInfo>
+#include <QLoggingCategory>
#include <QStringList>
#include <QScopedPointer>
#include <QDebug>
@@ -66,22 +69,39 @@
#include <cstring>
#include <cstdlib>
-#define VERSION_MAJ 1
-#define VERSION_MIN 1
-#define VERSION_STR "1.1"
-
#define FILE_OPEN_EVENT_WAIT_TIME 3000 // ms
+enum QmlApplicationType {
+ QmlApplicationTypeUnknown
+ , QmlApplicationTypeCore
+#ifdef QT_GUI_LIB
+ , QmlApplicationTypeGui
+#ifdef QT_WIDGETS_LIB
+ , QmlApplicationTypeWidget
+#endif // QT_WIDGETS_LIB
+#endif // QT_GUI_LIB
+};
+
+static QmlApplicationType applicationType =
+#ifndef QT_GUI_LIB
+ QmlApplicationTypeCore;
+#else
+ QmlApplicationTypeGui;
+#endif // QT_GUI_LIB
+
static Config *conf = nullptr;
static QQmlApplicationEngine *qae = nullptr;
#if defined(Q_OS_DARWIN) || defined(QT_GUI_LIB)
static int exitTimerId = -1;
#endif
-bool verboseMode = false;
+static const QString iconResourcePath(QStringLiteral(":/qt-project.org/QmlRuntime/resources/qml-64.png"));
+static const QString confResourcePath(QStringLiteral(":/qt-project.org/QmlRuntime/conf/"));
+static bool verboseMode = false;
+static bool quietMode = false;
static void loadConf(const QString &override, bool quiet) // Terminates app on failure
{
- const QString defaultFileName = QLatin1String("configuration.qml");
+ const QString defaultFileName = QLatin1String("default.qml");
QUrl settingsUrl;
bool builtIn = false; //just for keeping track of the warning
if (override.isEmpty()) {
@@ -91,29 +111,38 @@ static void loadConf(const QString &override, bool quiet) // Terminates app on f
settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
} else {
// ### If different built-in configs are needed per-platform, just apply QFileSelector to the qrc conf.qml path
- settingsUrl = QUrl(QLatin1String("qrc:///qt-project.org/QmlRuntime/conf/") + defaultFileName);
+ fi.setFile(confResourcePath + defaultFileName);
+ settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
builtIn = true;
}
} else {
QFileInfo fi;
- fi.setFile(override);
- if (!fi.exists()) {
- printf("qml: Couldn't find required configuration file: %s\n",
- qPrintable(QDir::toNativeSeparators(fi.absoluteFilePath())));
- exit(1);
+ fi.setFile(confResourcePath + override + QLatin1String(".qml"));
+ if (fi.exists()) {
+ settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
+ builtIn = true;
+ } else {
+ fi.setFile(override);
+ if (!fi.exists()) {
+ printf("qml: Couldn't find required configuration file: %s\n",
+ qPrintable(QDir::toNativeSeparators(fi.absoluteFilePath())));
+ exit(1);
+ }
+ settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
}
- settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath());
}
if (!quiet) {
printf("qml: %s\n", QLibraryInfo::build());
- if (builtIn)
- printf("qml: Using built-in configuration.\n");
- else
- printf("qml: Using configuration file: %s\n",
+ if (builtIn) {
+ printf("qml: Using built-in configuration: %s\n",
+ qPrintable(override.isEmpty() ? defaultFileName : override));
+ } else {
+ printf("qml: Using configuration: %s\n",
qPrintable(settingsUrl.isLocalFile()
? QDir::toNativeSeparators(settingsUrl.toLocalFile())
: settingsUrl.toString()));
+ }
}
// TODO: When we have better engine control, ban QtQuick* imports on this engine
@@ -127,15 +156,32 @@ static void loadConf(const QString &override, bool quiet) // Terminates app on f
}
}
-#ifdef QT_GUI_LIB
+void noFilesGiven()
+{
+ if (!quietMode)
+ printf("qml: No files specified. Terminating.\n");
+ exit(1);
+}
+
+static void listConfFiles()
+{
+ QDir confResourceDir(confResourcePath);
+ printf("%s\n", qPrintable(QCoreApplication::translate("main", "Built-in configurations:")));
+ for (const QFileInfo &fi : confResourceDir.entryInfoList(QDir::Files))
+ printf(" %s\n", qPrintable(fi.baseName()));
+ exit(0);
+}
-void noFilesGiven();
+#ifdef QT_GUI_LIB
// Loads qml after receiving a QFileOpenEvent
class LoaderApplication : public QGuiApplication
{
public:
- LoaderApplication(int& argc, char **argv) : QGuiApplication(argc, argv) {}
+ LoaderApplication(int& argc, char **argv) : QGuiApplication(argc, argv)
+ {
+ setWindowIcon(QIcon(iconResourcePath));
+ }
bool event(QEvent *ev) override
{
@@ -175,8 +221,8 @@ public:
connect(e, &QQmlEngine::exit, this, &LoadWatcher::exit);
}
- bool earlyExit = false;
int returnCode = 0;
+ bool earlyExit = false;
public Q_SLOTS:
void checkFinished(QObject *o, const QUrl &url)
@@ -217,8 +263,8 @@ private:
void checkForWindow(QObject *o);
private:
- int expectedFileCount;
bool haveWindow = false;
+ int expectedFileCount;
};
void LoadWatcher::contain(QObject *o, const QUrl &containPath)
@@ -278,93 +324,18 @@ void quietMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, const Q
exit(-1);
case QtCriticalMsg:
case QtDebugMsg:
+ case QtInfoMsg:
case QtWarningMsg:
- default:
;
}
}
-
-// ### Should command line arguments have translations? Qt creator doesn't, so maybe it's not worth it.
-enum QmlApplicationType {
- QmlApplicationTypeUnknown
- , QmlApplicationTypeCore
-#ifdef QT_GUI_LIB
- , QmlApplicationTypeGui
-#ifdef QT_WIDGETS_LIB
- , QmlApplicationTypeWidget
-#endif // QT_WIDGETS_LIB
-#endif // QT_GUI_LIB
-};
-
-#ifndef QT_GUI_LIB
-QmlApplicationType applicationType = QmlApplicationTypeCore;
-#else
-QmlApplicationType applicationType = QmlApplicationTypeGui;
-#endif // QT_GUI_LIB
-bool quietMode = false;
-void printVersion()
-{
- printf("qml binary version ");
- printf(VERSION_STR);
- printf("\nbuilt with Qt version ");
- printf(QT_VERSION_STR);
- printf("\n");
- exit(0);
-}
-
-void printUsage()
-{
- printf("Usage: qml [options] [files] [-- args]\n");
- printf("\n");
- printf("Any unknown argument before '--' will be treated as a QML file to be loaded.\n");
- printf("Any number of QML files can be loaded. They will share the same engine.\n");
- printf("'gui' application type is only available if the QtGui module is available.\n");
- printf("'widget' application type is only available if the QtWidgets module is available.\n");
- printf("\n");
- printf("General Options:\n");
- printf("\t-h, -help..................... Print this usage information and exit.\n");
- printf("\t-v, -version.................. Print the version information and exit.\n");
-#ifdef QT_GUI_LIB
-#ifndef QT_WIDGETS_LIB
- printf("\t-apptype [core|gui] .......... Select which application class to use. Default is gui.\n");
-#else
- printf("\t-apptype [core|gui|widget] ... Select which application class to use. Default is gui.\n");
-#endif // QT_WIDGETS_LIB
-#endif // QT_GUI_LIB
- printf("\t-quiet ....................... Suppress all output.\n");
- printf("\t-I [path] .................... Prepend the given path to the import paths.\n");
- printf("\t-f [file] .................... Load the given file as a QML file.\n");
- printf("\t-config [file] ............... Load the given file as the configuration file.\n");
- printf("\t-- ........................... Arguments after this one are ignored by the launcher, but may be used within the QML application.\n");
- printf("\tGL options:\n");
- printf("\t-desktop.......................Force use of desktop GL (AA_UseDesktopOpenGL)\n");
- printf("\t-gles..........................Force use of GLES (AA_UseOpenGLES)\n");
- printf("\t-software......................Force use of software rendering (AA_UseOpenGLES)\n");
- printf("\t-scaling.......................Enable High DPI scaling (AA_EnableHighDpiScaling)\n");
- printf("\t-no-scaling....................Disable High DPI scaling (AA_DisableHighDpiScaling)\n");
- printf("\tDebugging options:\n");
- printf("\t-verbose ..................... Print information about what qml is doing, like specific file urls being loaded.\n");
- printf("\t-translation [file] .......... Load the given file as the translations file.\n");
- printf("\t-dummy-data [directory] ...... Load QML files from the given directory as context properties.\n");
- printf("\t-slow-animations ............. Run all animations in slow motion.\n");
- printf("\t-fixed-animations ............ Run animations off animation tick rather than wall time.\n");
- exit(0);
-}
-
-void noFilesGiven()
-{
- if (!quietMode)
- printf("qml: No files specified. Terminating.\n");
- exit(1);
-}
-
// Called before application initialization, removes arguments it uses
void getAppFlags(int &argc, char **argv)
{
#ifdef QT_GUI_LIB
for (int i=0; i<argc; i++) {
- if (!strcmp(argv[i], "-apptype")) { // Must be done before application, as it selects application
+ if (!strcmp(argv[i], "--apptype") || !strcmp(argv[i], "-a") || !strcmp(argv[i], "-apptype")) {
applicationType = QmlApplicationTypeUnknown;
if (i+1 < argc) {
if (!strcmp(argv[i+1], "core"))
@@ -376,15 +347,6 @@ void getAppFlags(int &argc, char **argv)
applicationType = QmlApplicationTypeWidget;
#endif // QT_WIDGETS_LIB
}
-
- if (applicationType == QmlApplicationTypeUnknown) {
-#ifndef QT_WIDGETS_LIB
- printf("-apptype must be followed by one of the following: core gui\n");
-#else
- printf("-apptype must be followed by one of the following: core gui widget\n");
-#endif // QT_WIDGETS_LIB
- printUsage();
- }
for (int j=i; j<argc-2; j++)
argv[j] = argv[j+2];
argc -= 2;
@@ -438,9 +400,6 @@ int main(int argc, char *argv[])
getAppFlags(argc, argv);
QCoreApplication *app = nullptr;
switch (applicationType) {
- case QmlApplicationTypeCore:
- app = new QCoreApplication(argc, argv);
- break;
#ifdef QT_GUI_LIB
case QmlApplicationTypeGui:
app = new LoaderApplication(argc, argv);
@@ -448,11 +407,14 @@ int main(int argc, char *argv[])
#ifdef QT_WIDGETS_LIB
case QmlApplicationTypeWidget:
app = new QApplication(argc, argv);
+ static_cast<QApplication *>(app)->setWindowIcon(QIcon(iconResourcePath));
break;
#endif // QT_WIDGETS_LIB
#endif // QT_GUI_LIB
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "impossible case");
+ case QmlApplicationTypeCore:
+ Q_FALLTHROUGH();
+ default: // QmlApplicationTypeUnknown: not allowed, but we'll exit after checking apptypeOption below
+ app = new QCoreApplication(argc, argv);
break;
}
@@ -470,68 +432,130 @@ int main(int argc, char *argv[])
QString dummyDir;
// Handle main arguments
- const QStringList argList = app->arguments();
- for (int i = 1; i < argList.count(); i++) {
- const QString &arg = argList[i];
- if (arg == QLatin1String("-quiet"))
- quietMode = true;
- else if (arg == QLatin1String("-v") || arg == QLatin1String("-version"))
- printVersion();
- else if (arg == QLatin1String("-h") || arg == QLatin1String("-help"))
- printUsage();
- else if (arg == QLatin1String("--"))
- break;
- else if (arg == QLatin1String("-verbose"))
- verboseMode = true;
+ QCommandLineParser parser;
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+ parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
+ const QCommandLineOption helpOption = parser.addHelpOption();
+ const QCommandLineOption versionOption = parser.addVersionOption();
+#ifdef QT_GUI_LIB
+ QCommandLineOption apptypeOption(QStringList() << QStringLiteral("a") << QStringLiteral("apptype"),
+ QCoreApplication::translate("main", "Select which application class to use. Default is gui."),
+#ifdef QT_WIDGETS_LIB
+ QStringLiteral("core|gui|widget"));
+#else
+ QStringLiteral("core|gui"));
+#endif // QT_WIDGETS_LIB
+ parser.addOption(apptypeOption); // Just for the help text... we've already handled this argument above
+#endif // QT_GUI_LIB
+ QCommandLineOption importOption(QStringLiteral("I"),
+ QCoreApplication::translate("main", "Prepend the given path to the import paths."), QStringLiteral("path"));
+ parser.addOption(importOption);
+ QCommandLineOption qmlFileOption(QStringLiteral("f"),
+ QCoreApplication::translate("main", "Load the given file as a QML file."), QStringLiteral("file"));
+ parser.addOption(qmlFileOption);
+ QCommandLineOption configOption(QStringList() << QStringLiteral("c") << QStringLiteral("config"),
+ QCoreApplication::translate("main", "Load the given built-in configuration or configuration file."), QStringLiteral("file"));
+ parser.addOption(configOption);
+ QCommandLineOption listConfOption(QStringList() << QStringLiteral("list-conf"),
+ QCoreApplication::translate("main", "List the built-in configurations."));
+ parser.addOption(listConfOption);
+ QCommandLineOption translationOption(QStringLiteral("translation"),
+ QCoreApplication::translate("main", "Load the given file as the translations file."), QStringLiteral("file"));
+ parser.addOption(translationOption);
+ QCommandLineOption dummyDataOption(QStringLiteral("dummy-data"),
+ QCoreApplication::translate("main", "Load QML files from the given directory as context properties."), QStringLiteral("file"));
+ parser.addOption(dummyDataOption);
+ // OpenGL options
+ QCommandLineOption glDesktopOption(QStringLiteral("desktop"),
+ QCoreApplication::translate("main", "Force use of desktop OpenGL (AA_UseDesktopOpenGL)."));
+ parser.addOption(glDesktopOption);
+ QCommandLineOption glEsOption(QStringLiteral("gles"),
+ QCoreApplication::translate("main", "Force use of GLES (AA_UseOpenGLES)."));
+ parser.addOption(glEsOption);
+ QCommandLineOption glSoftwareOption(QStringLiteral("software"),
+ QCoreApplication::translate("main", "Force use of software rendering (AA_UseSoftwareOpenGL)."));
+ parser.addOption(glSoftwareOption);
+ QCommandLineOption scalingOption(QStringLiteral("scaling"),
+ QCoreApplication::translate("main", "Enable High DPI scaling (AA_EnableHighDpiScaling)."));
+ parser.addOption(scalingOption);
+ QCommandLineOption noScalingOption(QStringLiteral("no-scaling"),
+ QCoreApplication::translate("main", "Disable High DPI scaling (AA_DisableHighDpiScaling)."));
+ parser.addOption(noScalingOption);
+ // Debugging and verbosity options
+ QCommandLineOption quietOption(QStringLiteral("quiet"),
+ QCoreApplication::translate("main", "Suppress all output."));
+ parser.addOption(quietOption);
+ QCommandLineOption verboseOption(QStringLiteral("verbose"),
+ QCoreApplication::translate("main", "Print information about what qml is doing, like specific file URLs being loaded."));
+ parser.addOption(verboseOption);
+ QCommandLineOption slowAnimationsOption(QStringLiteral("slow-animations"),
+ QCoreApplication::translate("main", "Run all animations in slow motion."));
+ parser.addOption(slowAnimationsOption);
+ QCommandLineOption fixedAnimationsOption(QStringLiteral("fixed-animations"),
+ QCoreApplication::translate("main", "Run animations off animation tick rather than wall time."));
+ parser.addOption(fixedAnimationsOption);
+ // Positional arguments
+ parser.addPositionalArgument("files",
+ QCoreApplication::translate("main", "Any number of QML files can be loaded. They will share the same engine."), "[files...]");
+ parser.addPositionalArgument("args",
+ QCoreApplication::translate("main", "Arguments after '--' are ignored, but passed through to the application.arguments variable in QML."), "[-- args...]");
+
+ if (!parser.parse(QCoreApplication::arguments())) {
+ qWarning() << parser.errorText();
+ exit(1);
+ }
+ if (parser.isSet(versionOption))
+ parser.showVersion();
+ if (parser.isSet(helpOption))
+ parser.showHelp();
+ if (parser.isSet(listConfOption))
+ listConfFiles();
+ if (applicationType == QmlApplicationTypeUnknown) {
+#ifdef QT_WIDGETS_LIB
+ qWarning() << QCoreApplication::translate("main", "--apptype must be followed by one of the following: core gui widget\n");
+#else
+ qWarning() << QCoreApplication::translate("main", "--apptype must be followed by one of the following: core gui\n");
+#endif // QT_WIDGETS_LIB
+ parser.showHelp();
+ }
+ if (parser.isSet(verboseOption))
+ verboseMode = true;
+ if (parser.isSet(quietOption)) {
+ quietMode = true;
+ verboseMode = false;
+ }
#if QT_CONFIG(qml_animation)
- else if (arg == QLatin1String("-slow-animations"))
- QUnifiedTimer::instance()->setSlowModeEnabled(true);
- else if (arg == QLatin1String("-fixed-animations"))
- QUnifiedTimer::instance()->setConsistentTiming(true);
+ if (parser.isSet(slowAnimationsOption))
+ QUnifiedTimer::instance()->setSlowModeEnabled(true);
+ if (parser.isSet(fixedAnimationsOption))
+ QUnifiedTimer::instance()->setConsistentTiming(true);
#endif
- else if (arg == QLatin1String("-I")) {
- if (i+1 == argList.count())
- continue; // Invalid usage, but just ignore it
- e.addImportPath(argList[i+1]);
- i++;
- } else if (arg == QLatin1String("-f")) {
- if (i+1 == argList.count())
- continue; // Invalid usage, but just ignore it
- files << argList[i+1];
- i++;
- } else if (arg == QLatin1String("-config")){
- if (i+1 == argList.count())
- continue; // Invalid usage, but just ignore it
- confFile = argList[i+1];
- i++;
- } else if (arg == QLatin1String("-translation")){
- if (i+1 == argList.count())
- continue; // Invalid usage, but just ignore it
- translationFile = argList[i+1];
- i++;
- } else if (arg == QLatin1String("-dummy-data")){
- if (i+1 == argList.count())
- continue; // Invalid usage, but just ignore it
- dummyDir = argList[i+1];
- i++;
- } else if (arg == QLatin1String("-gles")) {
- QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
- } else if (arg == QLatin1String("-software")) {
- QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
- } else if (arg == QLatin1String("-desktop")) {
- QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
- } else if (arg == QLatin1String("-scaling")) {
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- } else if (arg == QLatin1String("-no-scaling")) {
- QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
- } else {
- files << arg;
- }
+ if (parser.isSet(glEsOption))
+ QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
+ if (parser.isSet(glSoftwareOption))
+ QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
+ if (parser.isSet(glDesktopOption))
+ QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
+ if (parser.isSet(scalingOption))
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ if (parser.isSet(noScalingOption))
+ QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
+ for (const QString &importPath : parser.values(importOption))
+ e.addImportPath(importPath);
+ files << parser.values(qmlFileOption);
+ if (parser.isSet(configOption))
+ confFile = parser.value(configOption);
+ if (parser.isSet(translationOption))
+ translationFile = parser.value(translationOption);
+ if (parser.isSet(dummyDataOption))
+ dummyDir = parser.value(dummyDataOption);
+ for (QString posArg : parser.positionalArguments()) {
+ if (posArg == QLatin1String("--"))
+ break;
+ else
+ files << posArg;
}
- if (quietMode && verboseMode)
- verboseMode = false;
-
#if QT_CONFIG(translation)
// Need to be installed before QQmlApplicationEngine's automatic translation loading
// (qt_ translations are loaded there)
@@ -552,8 +576,10 @@ int main(int argc, char *argv[])
printf("qml: Translation file specified, but Qt built without translation support.\n");
#endif
- if (quietMode)
+ if (quietMode) {
qInstallMessageHandler(quietMessageHandler);
+ QLoggingCategory::setFilterRules(QStringLiteral("*=false"));
+ }
if (files.count() <= 0) {
#if defined(Q_OS_DARWIN)