diff options
Diffstat (limited to 'tools/qml/main.cpp')
-rw-r--r-- | tools/qml/main.cpp | 243 |
1 files changed, 147 insertions, 96 deletions
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 8e5a493bcd..da544c5563 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Research In Motion. -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Research In Motion. +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "conf.h" @@ -61,6 +36,7 @@ #include <qqmlfileselector.h> #include <private/qtqmlglobal_p.h> +#include <private/qqmlimport_p.h> #if QT_CONFIG(qml_animation) #include <private/qabstractanimation_p.h> #endif @@ -72,6 +48,8 @@ #define FILE_OPEN_EVENT_WAIT_TIME 3000 // ms +Q_LOGGING_CATEGORY(lcDeprecated, "qt.tools.qml.deprecated") + enum QmlApplicationType { QmlApplicationTypeUnknown , QmlApplicationTypeCore @@ -95,10 +73,18 @@ static QQmlApplicationEngine *qae = nullptr; #if defined(Q_OS_DARWIN) || defined(QT_GUI_LIB) static int exitTimerId = -1; #endif -static const QString iconResourcePath(QStringLiteral(":/qt-project.org/QmlRuntime/resources/qml-64.png")); -static const QString confResourcePath(QStringLiteral(":/qt-project.org/QmlRuntime/conf/")); +static const QString iconResourcePath(QStringLiteral(":/qt-project.org/imports/QmlRuntime/Config/resources/qml-64.png")); +static const QString confResourcePath(QStringLiteral(":/qt-project.org/imports/QmlRuntime/Config/")); +static const QString customConfFileName(QStringLiteral("configuration.qml")); static bool verboseMode = false; static bool quietMode = false; +static bool glShareContexts = true; +static bool disableShaderCache = true; +#if defined(QT_GUI_LIB) +static bool requestAlphaChannel = false; +static bool requestMSAA = false; +static bool requestCoreProfile = false; +#endif static void loadConf(const QString &override, bool quiet) // Terminates app on failure { @@ -109,27 +95,31 @@ static void loadConf(const QString &override, bool quiet) // Terminates app on f QFileInfo fi; fi.setFile(QStandardPaths::locate(QStandardPaths::AppDataLocation, defaultFileName)); if (fi.exists()) { - settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath()); + settingsUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(fi.absoluteFilePath()); } else { // ### If different built-in configs are needed per-platform, just apply QFileSelector to the qrc conf.qml path fi.setFile(confResourcePath + defaultFileName); - settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath()); + settingsUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(fi.absoluteFilePath()); builtIn = true; } } else { QFileInfo fi; fi.setFile(confResourcePath + override + QLatin1String(".qml")); if (fi.exists()) { - settingsUrl = QUrl::fromLocalFile(fi.absoluteFilePath()); + settingsUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(fi.absoluteFilePath()); builtIn = true; } else { - fi.setFile(override); + fi.setFile(QDir(QStandardPaths::locate(QStandardPaths::AppConfigLocation, override, QStandardPaths::LocateDirectory)), customConfFileName); + if (fi.exists()) + settingsUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(fi.absoluteFilePath()); + 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 = QQmlImports::urlFromLocalFileOrQrcOrUrl(fi.absoluteFilePath()); } } @@ -166,10 +156,38 @@ void noFilesGiven() static void listConfFiles() { - QDir confResourceDir(confResourcePath); + const 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())); + for (const QFileInfo &fi : confResourceDir.entryInfoList(QDir::Files)) { + if (fi.completeSuffix() != QLatin1String("qml")) + continue; + + const QString baseName = fi.baseName(); + if (baseName.isEmpty() || baseName[0].isUpper()) + continue; + + printf(" %s\n", qPrintable(baseName)); + } + printf("%s\n", qPrintable(QCoreApplication::translate("main", "Other configurations:"))); + bool foundOther = false; + const QStringList otherLocations = QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation); + for (const auto &confDirPath : otherLocations) { + const QDir confDir(confDirPath); + for (const QFileInfo &fi : confDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { + foundOther = true; + if (verboseMode) + printf(" %s\n", qPrintable(fi.absoluteFilePath())); + else + printf(" %s\n", qPrintable(fi.baseName())); + } + } + if (!foundOther) + printf(" %s\n", qPrintable(QCoreApplication::translate("main", "none"))); + if (verboseMode) { + printf("%s\n", qPrintable(QCoreApplication::translate("main", "Checked in:"))); + for (const auto &confDirPath : otherLocations) + printf(" %s\n", qPrintable(confDirPath)); + } exit(0); } @@ -230,18 +248,17 @@ public Q_SLOTS: { Q_UNUSED(url); if (o) { - checkForWindow(o); + ++createdObjects; if (conf && qae) - for (PartialScene *ps : qAsConst(conf->completers)) + for (PartialScene *ps : std::as_const(conf->completers)) if (o->inherits(ps->itemType().toUtf8().constData())) contain(o, ps->container()); } - if (haveWindow) - return; - if (! --expectedFileCount) { + if (!--expectedFileCount && !createdObjects) { printf("qml: Did not load any objects, exiting.\n"); - std::exit(2); // Different return code from qFatal + exit(2); + QCoreApplication::exit(2); } } @@ -257,11 +274,10 @@ public Q_SLOTS: private: void contain(QObject *o, const QUrl &containPath); - void checkForWindow(QObject *o); private: - bool haveWindow = false; int expectedFileCount; + int createdObjects = 0; }; void LoadWatcher::contain(QObject *o, const QUrl &containPath) @@ -270,7 +286,7 @@ void LoadWatcher::contain(QObject *o, const QUrl &containPath) QObject *o2 = c.create(); if (!o2) return; - checkForWindow(o2); + o2->setParent(this); bool success = false; int idx; if ((idx = o2->metaObject()->indexOfProperty("containedObject")) != -1) @@ -279,16 +295,6 @@ void LoadWatcher::contain(QObject *o, const QUrl &containPath) o->setParent(o2); // Set QObject parent, and assume container will react as needed } -void LoadWatcher::checkForWindow(QObject *o) -{ -#if defined(QT_GUI_LIB) - if (o->isWindowType() && o->inherits("QQuickWindow")) - haveWindow = true; -#else - Q_UNUSED(o); -#endif // QT_GUI_LIB -} - void quietMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, const QString &msg) { Q_UNUSED(ctxt); @@ -330,6 +336,16 @@ static void getAppFlags(int argc, char **argv) QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); } else if (!strcmp(argv[i], "-software") || !strcmp(argv[i], "--software")) { QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); + } else if (!strcmp(argv[i], "-disable-context-sharing") || !strcmp(argv[i], "--disable-context-sharing")) { + glShareContexts = false; + } else if (!strcmp(argv[i], "-enable-shader-cache") || !strcmp(argv[i], "--enable-shader-cache")) { + disableShaderCache = false; + } else if (!strcmp(argv[i], "-transparent") || !strcmp(argv[i], "--transparent")) { + requestAlphaChannel = true; + } else if (!strcmp(argv[i], "-multisample") || !strcmp(argv[i], "--multisample")) { + requestMSAA = true; + } else if (!strcmp(argv[i], "-core-profile") || !strcmp(argv[i], "--core-profile")) { + requestCoreProfile = true; } } #else @@ -338,6 +354,7 @@ static void getAppFlags(int argc, char **argv) #endif // QT_GUI_LIB } +#if QT_DEPRECATED_SINCE(6, 3) static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory) { QDir dir(directory+"/dummydata", "*.qml"); @@ -355,16 +372,44 @@ static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory) if (dummyData && !quietMode) { printf("qml: Loaded dummy data: %s\n", qPrintable(dir.filePath(qml))); - qml.truncate(qml.length()-4); + qml.truncate(qml.size()-4); engine.rootContext()->setContextProperty(qml, dummyData); dummyData->setParent(&engine); } } } +#endif int main(int argc, char *argv[]) { getAppFlags(argc, argv); + + // Must set the default QSurfaceFormat before creating the app object if + // AA_ShareOpenGLContexts is going to be set. +#if defined(QT_GUI_LIB) + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(24); + surfaceFormat.setStencilBufferSize(8); + if (requestMSAA) + surfaceFormat.setSamples(4); + if (requestAlphaChannel) + surfaceFormat.setAlphaBufferSize(8); + if (qEnvironmentVariableIsSet("QSG_CORE_PROFILE") + || qEnvironmentVariableIsSet("QML_CORE_PROFILE") + || requestCoreProfile) + { + // intentionally requesting 4.1 core to play nice with macOS + surfaceFormat.setVersion(4, 1); + surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); + } + QSurfaceFormat::setDefaultFormat(surfaceFormat); +#endif + + if (glShareContexts) + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + if (disableShaderCache) + QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache); + std::unique_ptr<QCoreApplication> app; switch (applicationType) { #ifdef QT_GUI_LIB @@ -390,18 +435,16 @@ int main(int argc, char *argv[]) app->setOrganizationDomain("qt-project.org"); QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); - QQmlApplicationEngine e; QStringList files; QString confFile; QString translationFile; - QString dummyDir; // Handle main arguments QCommandLineParser parser; parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments); - const QCommandLineOption helpOption = parser.addHelpOption(); - const QCommandLineOption versionOption = parser.addVersionOption(); + parser.addHelpOption(); + 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."), @@ -427,9 +470,11 @@ int main(int argc, char *argv[]) QCommandLineOption translationOption(QStringLiteral("translation"), QCoreApplication::translate("main", "Load the given file as the translations file."), QStringLiteral("file")); parser.addOption(translationOption); +#if QT_DEPRECATED_SINCE(6, 3) QCommandLineOption dummyDataOption(QStringLiteral("dummy-data"), - QCoreApplication::translate("main", "Load QML files from the given directory as context properties."), QStringLiteral("file")); + QCoreApplication::translate("main", "Load QML files from the given directory as context properties. (deprecated)"), QStringLiteral("file")); parser.addOption(dummyDataOption); +#endif #ifdef QT_GUI_LIB // OpenGL options QCommandLineOption glDesktopOption(QStringLiteral("desktop"), @@ -441,7 +486,24 @@ int main(int argc, char *argv[]) QCommandLineOption glSoftwareOption(QStringLiteral("software"), QCoreApplication::translate("main", "Force use of software rendering (AA_UseSoftwareOpenGL).")); parser.addOption(glSoftwareOption); // Just for the help text... we've already handled this argument above + QCommandLineOption glCoreProfile(QStringLiteral("core-profile"), + QCoreApplication::translate("main", "Force use of OpenGL Core Profile.")); + parser.addOption(glCoreProfile); // Just for the help text... we've already handled this argument above + QCommandLineOption glContextSharing(QStringLiteral("disable-context-sharing"), + QCoreApplication::translate("main", "Disable the use of a shared GL context for QtQuick Windows")); + parser.addOption(glContextSharing); // Just for the help text... we've already handled this argument above + // Options relevant for other 3D APIs as well + QCommandLineOption shaderCaching(QStringLiteral("enable-shader-cache"), + QCoreApplication::translate("main", "Enable persistent caching of generated shaders")); + parser.addOption(shaderCaching); // Just for the help text... we've already handled this argument above + QCommandLineOption transparentOption(QStringLiteral("transparent"), + QCoreApplication::translate("main", "Requests an alpha channel in order to enable semi-transparent windows.")); + parser.addOption(transparentOption); // Just for the help text... we've already handled this argument above + QCommandLineOption multisampleOption(QStringLiteral("multisample"), + QCoreApplication::translate("main", "Requests 4x multisample antialiasing.")); + parser.addOption(multisampleOption); // Just for the help text... we've already handled this argument above #endif // QT_GUI_LIB + // Debugging and verbosity options QCommandLineOption quietOption(QStringLiteral("quiet"), QCoreApplication::translate("main", "Suppress all output.")); @@ -457,7 +519,7 @@ int main(int argc, char *argv[]) parser.addOption(fixedAnimationsOption); QCommandLineOption rhiOption(QStringList() << QStringLiteral("r") << QStringLiteral("rhi"), QCoreApplication::translate("main", "Set the backend for the Qt graphics abstraction (RHI). " - "Backend is one of: default, vulkan, metal, d3d11, gl"), + "Backend is one of: default, vulkan, metal, d3d11, d3d12, opengl"), QStringLiteral("backend")); parser.addOption(rhiOption); QCommandLineOption selectorOption(QStringLiteral("S"), QCoreApplication::translate("main", @@ -470,14 +532,13 @@ int main(int argc, char *argv[]) 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); + parser.process(*app); + if (parser.isSet(verboseOption)) + verboseMode = true; + if (parser.isSet(quietOption)) { + quietMode = true; + verboseMode = false; } - if (parser.isSet(versionOption)) - parser.showVersion(); - if (parser.isSet(helpOption)) - parser.showHelp(); if (parser.isSet(listConfOption)) listConfFiles(); if (applicationType == QmlApplicationTypeUnknown) { @@ -488,18 +549,15 @@ int main(int argc, char *argv[]) #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) if (parser.isSet(slowAnimationsOption)) QUnifiedTimer::instance()->setSlowModeEnabled(true); if (parser.isSet(fixedAnimationsOption)) QUnifiedTimer::instance()->setConsistentTiming(true); #endif + + QQmlApplicationEngine e; + for (const QString &importPath : parser.values(importOption)) e.addImportPath(importPath); @@ -510,24 +568,11 @@ int main(int argc, char *argv[]) if (!customSelectors.isEmpty()) e.setExtraFileSelectors(customSelectors); -#if defined(QT_GUI_LIB) - if (qEnvironmentVariableIsSet("QSG_CORE_PROFILE") || qEnvironmentVariableIsSet("QML_CORE_PROFILE")) { - QSurfaceFormat surfaceFormat; - surfaceFormat.setStencilBufferSize(8); - surfaceFormat.setDepthBufferSize(24); - surfaceFormat.setVersion(4, 1); - surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); - QSurfaceFormat::setDefaultFormat(surfaceFormat); - } -#endif - 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); if (parser.isSet(rhiOption)) { const QString rhiBackend = parser.value(rhiOption); if (rhiBackend == QLatin1String("default")) @@ -545,9 +590,8 @@ int main(int argc, char *argv[]) #if QT_CONFIG(translation) // Need to be installed before QQmlApplicationEngine's automatic translation loading // (qt_ translations are loaded there) + QTranslator translator; if (!translationFile.isEmpty()) { - QTranslator translator; - if (translator.load(translationFile)) { app->installTranslator(&translator); if (verboseMode) @@ -567,7 +611,7 @@ int main(int argc, char *argv[]) QLoggingCategory::setFilterRules(QStringLiteral("*=false")); } - if (files.count() <= 0) { + if (files.size() <= 0) { #if defined(Q_OS_DARWIN) && defined(QT_GUI_LIB) if (applicationType == QmlApplicationTypeGui) exitTimerId = static_cast<LoaderApplication *>(app.get())->startTimer(FILE_OPEN_EVENT_WAIT_TIME); @@ -580,13 +624,20 @@ int main(int argc, char *argv[]) loadConf(confFile, !verboseMode); // Load files - QScopedPointer<LoadWatcher> lw(new LoadWatcher(&e, files.count())); + QScopedPointer<LoadWatcher> lw(new LoadWatcher(&e, files.size())); +#if QT_DEPRECATED_SINCE(6, 3) + QString dummyDir; + if (parser.isSet(dummyDataOption)) + dummyDir = parser.value(dummyDataOption); // Load dummy data before loading QML-files - if (!dummyDir.isEmpty() && QFileInfo (dummyDir).isDir()) + if (!dummyDir.isEmpty() && QFileInfo (dummyDir).isDir()) { + qCWarning(lcDeprecated()) << "Warning: the qml --dummy-data option is deprecated and will be removed in a future version of Qt."; loadDummyDataFiles(e, dummyDir); + } +#endif - for (const QString &path : qAsConst(files)) { + for (const QString &path : std::as_const(files)) { QUrl url = QUrl::fromUserInput(path, QDir::currentPath(), QUrl::AssumeLocalFile); if (verboseMode) printf("qml: loading %s\n", qPrintable(url.toString())); |