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.cpp243
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()));