summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/CMakeLists.txt5
-rw-r--r--src/tools/androiddeployqt/CMakeLists.txt13
-rw-r--r--src/tools/androiddeployqt/doc/src/androiddeployqt.qdoc237
-rw-r--r--src/tools/androiddeployqt/main.cpp1763
-rw-r--r--src/tools/androidtestrunner/CMakeLists.txt10
-rw-r--r--src/tools/androidtestrunner/main.cpp833
-rw-r--r--src/tools/bootstrap/CMakeLists.txt106
-rw-r--r--src/tools/cmake_automoc_parser/CMakeLists.txt8
-rw-r--r--src/tools/cmake_automoc_parser/main.cpp81
-rw-r--r--src/tools/configure.cmake9
-rw-r--r--src/tools/macdeployqt/CMakeLists.txt3
-rw-r--r--src/tools/macdeployqt/macdeployqt/CMakeLists.txt6
-rw-r--r--src/tools/macdeployqt/macdeployqt/main.cpp29
-rw-r--r--src/tools/macdeployqt/shared/shared.cpp154
-rw-r--r--src/tools/macdeployqt/shared/shared.h34
-rw-r--r--src/tools/moc/CMakeLists.txt15
-rw-r--r--src/tools/moc/cbordevice.h31
-rw-r--r--src/tools/moc/collectjson.cpp31
-rw-r--r--src/tools/moc/collectjson.h29
-rw-r--r--src/tools/moc/generator.cpp669
-rw-r--r--src/tools/moc/generator.h36
-rw-r--r--src/tools/moc/keywords.cpp423
-rw-r--r--src/tools/moc/main.cpp109
-rw-r--r--src/tools/moc/moc.cpp589
-rw-r--r--src/tools/moc/moc.h77
-rw-r--r--src/tools/moc/outputrevision.h29
-rw-r--r--src/tools/moc/parser.cpp105
-rw-r--r--src/tools/moc/parser.h40
-rw-r--r--src/tools/moc/ppkeywords.cpp29
-rw-r--r--src/tools/moc/preprocessor.cpp176
-rw-r--r--src/tools/moc/preprocessor.h41
-rw-r--r--src/tools/moc/symbols.h139
-rw-r--r--src/tools/moc/token.cpp29
-rw-r--r--src/tools/moc/token.h31
-rwxr-xr-xsrc/tools/moc/util/generate.sh33
-rw-r--r--src/tools/moc/util/generate_keywords.cpp31
-rw-r--r--src/tools/moc/util/licenseheader.cpp.in3
-rw-r--r--src/tools/moc/util/licenseheader.txt28
-rw-r--r--src/tools/moc/utils.h71
-rw-r--r--src/tools/qdbuscpp2xml/CMakeLists.txt26
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp128
-rw-r--r--src/tools/qdbusxml2cpp/CMakeLists.txt26
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp1035
-rw-r--r--src/tools/qlalr/CMakeLists.txt17
-rw-r--r--src/tools/qlalr/compress.cpp35
-rw-r--r--src/tools/qlalr/compress.h29
-rw-r--r--src/tools/qlalr/cppgenerator.cpp141
-rw-r--r--src/tools/qlalr/cppgenerator.h35
-rw-r--r--src/tools/qlalr/dotgraph.cpp29
-rw-r--r--src/tools/qlalr/dotgraph.h29
-rw-r--r--src/tools/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp29
-rw-r--r--src/tools/qlalr/examples/dummy-xml/xml.g27
-rw-r--r--src/tools/qlalr/examples/glsl/build.sh29
-rw-r--r--src/tools/qlalr/examples/glsl/glsl-lex.l31
-rw-r--r--src/tools/qlalr/examples/glsl/glsl.g27
-rw-r--r--src/tools/qlalr/examples/lambda/lambda.g27
-rw-r--r--src/tools/qlalr/examples/lambda/main.cpp29
-rw-r--r--src/tools/qlalr/examples/qparser/calc.g27
-rw-r--r--src/tools/qlalr/examples/qparser/calc.l33
-rw-r--r--src/tools/qlalr/examples/qparser/qparser.cpp29
-rw-r--r--src/tools/qlalr/examples/qparser/qparser.h29
-rw-r--r--src/tools/qlalr/grammar.cpp29
-rw-r--r--src/tools/qlalr/grammar_p.h29
-rw-r--r--src/tools/qlalr/lalr.cpp65
-rw-r--r--src/tools/qlalr/lalr.g159
-rw-r--r--src/tools/qlalr/lalr.h44
-rw-r--r--src/tools/qlalr/main.cpp65
-rw-r--r--src/tools/qlalr/parsetable.cpp29
-rw-r--r--src/tools/qlalr/parsetable.h29
-rw-r--r--src/tools/qlalr/recognizer.cpp101
-rw-r--r--src/tools/qlalr/recognizer.h36
-rw-r--r--src/tools/qtpaths/CMakeLists.txt6
-rw-r--r--src/tools/qtpaths/qtpaths.cpp71
-rw-r--r--src/tools/qvkgen/CMakeLists.txt13
-rw-r--r--src/tools/qvkgen/qvkgen.cpp102
-rw-r--r--src/tools/rcc/CMakeLists.txt22
-rw-r--r--src/tools/rcc/main.cpp114
-rw-r--r--src/tools/rcc/rcc.cpp297
-rw-r--r--src/tools/rcc/rcc.h34
-rw-r--r--src/tools/shared/depfile_shared.h29
-rw-r--r--src/tools/shared/shellquote_shared.h82
-rw-r--r--src/tools/syncqt/CMakeLists.txt80
-rw-r--r--src/tools/syncqt/main.cpp1844
-rw-r--r--src/tools/tracegen/CMakeLists.txt12
-rw-r--r--src/tools/tracegen/ctf.cpp376
-rw-r--r--src/tools/tracegen/ctf.h12
-rw-r--r--src/tools/tracegen/etw.cpp130
-rw-r--r--src/tools/tracegen/etw.h40
-rw-r--r--src/tools/tracegen/helpers.cpp109
-rw-r--r--src/tools/tracegen/helpers.h60
-rw-r--r--src/tools/tracegen/lttng.cpp202
-rw-r--r--src/tools/tracegen/lttng.h40
-rw-r--r--src/tools/tracegen/panic.cpp53
-rw-r--r--src/tools/tracegen/panic.h41
-rw-r--r--src/tools/tracegen/provider.cpp326
-rw-r--r--src/tools/tracegen/provider.h85
-rw-r--r--src/tools/tracegen/qtheaders.cpp40
-rw-r--r--src/tools/tracegen/qtheaders.h40
-rw-r--r--src/tools/tracegen/tracegen.cpp55
-rw-r--r--src/tools/tracepointgen/CMakeLists.txt17
-rw-r--r--src/tools/tracepointgen/parser.cpp609
-rw-r--r--src/tools/tracepointgen/parser.h77
-rw-r--r--src/tools/tracepointgen/tracepointgen.cpp69
-rw-r--r--src/tools/tracepointgen/tracepointgen.h42
-rw-r--r--src/tools/uic/CMakeLists.txt16
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.cpp55
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.h29
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp53
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.h29
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp715
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h34
-rw-r--r--src/tools/uic/customwidgetsinfo.cpp133
-rw-r--r--src/tools/uic/customwidgetsinfo.h34
-rw-r--r--src/tools/uic/databaseinfo.cpp35
-rw-r--r--src/tools/uic/databaseinfo.h29
-rw-r--r--src/tools/uic/driver.cpp57
-rw-r--r--src/tools/uic/driver.h29
-rw-r--r--src/tools/uic/main.cpp185
-rw-r--r--src/tools/uic/option.h50
-rw-r--r--src/tools/uic/python/pythonwritedeclaration.cpp33
-rw-r--r--src/tools/uic/python/pythonwritedeclaration.h29
-rw-r--r--src/tools/uic/python/pythonwriteimports.cpp111
-rw-r--r--src/tools/uic/python/pythonwriteimports.h32
-rw-r--r--src/tools/uic/qclass_lib_map.h2
-rw-r--r--src/tools/uic/shared/language.cpp236
-rw-r--r--src/tools/uic/shared/language.h37
-rw-r--r--src/tools/uic/shared/writeincludesbase.cpp29
-rw-r--r--src/tools/uic/shared/writeincludesbase.h29
-rw-r--r--src/tools/uic/treewalker.cpp29
-rw-r--r--src/tools/uic/treewalker.h29
-rw-r--r--src/tools/uic/ui4.cpp1292
-rw-r--r--src/tools/uic/ui4.h45
-rw-r--r--src/tools/uic/uic.cpp71
-rw-r--r--src/tools/uic/uic.h29
-rw-r--r--src/tools/uic/utils.h31
-rw-r--r--src/tools/uic/validator.cpp29
-rw-r--r--src/tools/uic/validator.h29
-rw-r--r--src/tools/windeployqt/CMakeLists.txt13
-rw-r--r--src/tools/windeployqt/elfreader.cpp440
-rw-r--r--src/tools/windeployqt/elfreader.h176
-rw-r--r--src/tools/windeployqt/main.cpp1407
-rw-r--r--src/tools/windeployqt/qmlutils.cpp42
-rw-r--r--src/tools/windeployqt/qmlutils.h29
-rw-r--r--src/tools/windeployqt/qtmoduleinfo.cpp183
-rw-r--r--src/tools/windeployqt/qtmoduleinfo.h51
-rw-r--r--src/tools/windeployqt/qtplugininfo.cpp100
-rw-r--r--src/tools/windeployqt/qtplugininfo.h48
-rw-r--r--src/tools/windeployqt/utils.cpp308
-rw-r--r--src/tools/windeployqt/utils.h68
149 files changed, 10990 insertions, 9127 deletions
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 77348abcc7..df0d2c7016 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# The configure.cmake here does not get picked up automatically.
# Manually evaluate tool-related features.
include("${CMAKE_CURRENT_SOURCE_DIR}/configure.cmake")
@@ -16,7 +19,7 @@ endif()
if(QT_FEATURE_androiddeployqt)
add_subdirectory(androiddeployqt)
- if(QT_FEATURE_gui AND QT_FEATURE_systemsemaphore)
+ if(QT_FEATURE_gui AND QT_FEATURE_process AND QT_FEATURE_systemsemaphore)
add_subdirectory(androidtestrunner)
endif()
endif()
diff --git a/src/tools/androiddeployqt/CMakeLists.txt b/src/tools/androiddeployqt/CMakeLists.txt
index da4c524456..041d883877 100644
--- a/src/tools/androiddeployqt/CMakeLists.txt
+++ b/src/tools/androiddeployqt/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from androiddeployqt.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## androiddeployqt App:
@@ -8,14 +9,17 @@ qt_get_tool_target_name(target_name androiddeployqt)
qt_internal_add_tool(${target_name}
TARGET_DESCRIPTION "Qt Android Deployment Tool"
TOOLS_TARGET Core
+ USER_FACING
+ INSTALL_VERSIONED_LINK
SOURCES
main.cpp
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_FOREACH
- PUBLIC_LIBRARIES
- Qt::Core # special case
+ QT_NO_QPAIR
+ LIBRARIES
+ Qt::Core
INCLUDE_DIRECTORIES
../shared
)
@@ -24,9 +28,6 @@ set_target_properties(${target_name} PROPERTIES
WIN32_EXECUTABLE FALSE
)
-#### Keys ignored in scope 1:.:.:androiddeployqt.pro:<TRUE>:
-# _OPTION = "host_build"
-
## Scopes:
#####################################################################
diff --git a/src/tools/androiddeployqt/doc/src/androiddeployqt.qdoc b/src/tools/androiddeployqt/doc/src/androiddeployqt.qdoc
index b77d3182c5..b94d7f5c04 100644
--- a/src/tools/androiddeployqt/doc/src/androiddeployqt.qdoc
+++ b/src/tools/androiddeployqt/doc/src/androiddeployqt.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page android-deploy-qt-tool.html
@@ -31,132 +7,47 @@
\title The androiddeployqt Tool
\target androiddeployqt
- Building an application package is complex, so Qt comes with a tool which
- handles the work for you. The steps described in
- \l{Deploying an Application on Android} are handled by the androiddeployqt
- tool.
+ Building an Android package involves many steps, so Qt comes with a tool which
+ handles the work for you. The steps handled by the androiddeployqt
+ tool are described in \l{Deploying an Application on Android}.
\section1 Prerequisites Before Running androiddeployqt
- Before running the tool manually, you need to run \c qmake or \c CMake
- on your project to generate \c Makefiles and a \c JSON file (i.e.
- \c{android-project-deployment-settings.json}) containing important settings
+ Before running the tool manually, you need to configure your project with
+ \c CMake or \c qmake to generate \c Makefiles and a \c JSON file (i.e.
+ \c{android-<target_name>-deployment-settings.json}) containing important settings
used by \c androiddeployqt.
\note It is not recommended to modify the androiddeployqt JSON file.
- To prepare the build for androiddeployqt, it is recommended to build your
- project in a separate directory. Run the following commands:
+ To prepare the environment for androiddeployqt, configure your project in
+ a separate directory than your source directory. For more information on
+ configuring your project, see \l {Building Qt for Android Projects from Command Line}.
+ \section1 Command Line Arguments
- \badcode
- mkdir build-project
- cd build-project
- \endcode
-
- Followed by:
-
- For qmake:
- \badcode
- qmake ../project/project.pro
- make -j$(nproc)
- make -j$(nproc) apk_install_target
- \endcode
-
- For CMake:
- \badcode
- cmake --build
- \endcode
+ The only required command line arguments when running the tool are
+ \c {--input} and \c {--output}. Other command line arguments are optional but
+ useful. The list below is available by passing the \c {--help} argument to
+ androiddeployqt.
- \section1 Command Line Arguments
+ \quotefromfile main.cpp
+ \skipto Syntax: androiddeployqt --output <destination> [options]
+ \printuntil --help: Displays this information.
- The only required command line argument when running the tool is \c{--output}.
- Other command line arguments are optional but useful. Here's a quick overview.
- More information is available by passing the \c{--help} argument to androiddeployqt.
-
- \table
- \header
- \li Argument
- \li Brief Description
- \row
- \li \c{--output <destination>}
- \li Specifies the destination of the final package. Set this to
- \c{$ANDROID_BUILD_DIR}, that is the build directory where you installed
- your application binaries.
- \row
- \li \c{--input <file name>}
- \li This allows you to specify the generated \c JSON settings file.
- \c androiddeployqt will try to guess the file name based on the
- current working directory.
- \row
- \li \c{--aab}
- \li Generate an Android Application Bundle, rather than an APK. Note
- that this invalidates some of the other arguments, such as \c{--install}.
- \row
- \li \c{--deployment <mechanism>}
- \li Specify this to pick a different deployment mechanism than the
- default.
- \row
- \li \c{--install}
- \li Specify this to install the finished package on the target device
- or emulator. Note that if a previous version of the package is
- already installed, it will be uninstalled first, removing any
- data it might have stored locally.
- \row
- \li \c{--device <ID>}
- \li Specify the ID of the target device or emulator as reported by
- the \c adb tool. If an ID is specified, it will be passed to all
- calls to \c adb. If it is unspecified, no particular device or
- emulator will be requested by \c adb, causing it to pick a default
- instead.
- \row
- \li \c{--android-platform <platform>}
- \li The SDK platform used for building the Java code of the application.
- By default, the latest available platform is used.
- \row
- \li \c{--release}
- \li Specify this to create a release package instead of a debug package.
- With no other arguments, release packages are unsigned and cannot
- be installed to any device before they have been signed by a private
- key.
- \row
- \li \c{--sign <url> <alias>}
- \li Sign the resulting package. Specifying this also implies
- \c{--release}. The URL of the keystore file and the alias of the
- key have to be specified. Optionally, set the following environment
- variables to conceal the signing information
- \c QT_ANDROID_KEYSTORE_PATH, \c QT_ANDROID_KEYSTORE_ALIAS,
- \c QT_ANDROID_KEYSTORE_STORE_PASS, and \c QT_ANDROID_KEYSTORE_KEY_PASS.
- In addition, there are a number of options that can be specified
- which are passed through to the \c jarsigner tool.
- Pass \c{--help} to \c androiddeployqt for more information.
- \row
- \li \c{--jdk <path>}
- \li Specify the path to the Java Development Kit. This is only
- required for signing packages, as it is only used for finding
- the \c jarsigner tool. If it is unspecified, then \c androiddeployqt
- will attempt to detect \c jarsigner, either using the \c{JAVA_HOME}
- environment variable, or on the \c PATH.
- \row
- \li \c{--verbose}
- \li Specify this to output more information about what \c androiddeployqt is
- doing.
- \row
- \li \c{--help}
- \li Prints the help for the tool.
- \endtable
-
- With a project named \c project, to directly build the application package
- with \c androiddeployqt without deploying it the device, run the following:
+ With a \c project_name, to build the application package with \c androiddeployqt
+ without deploying it the device, run the following:
\badcode
- .androiddeployqt --input $BUILD_DIR/android-project-deployment-settings.json --output $ANDROID_BUILD_DIR
+ androiddeployqt --input <build_dir>/android-project_name-deployment-settings.json \
+ --output <build_dir>/android-build
\endcode
- To deploy the built package to the device:
+ To build and deploy the package to the device:
\badcode
- androiddeployqt --verbose --output $ANDROID_BUILD_DIR --no-build --input $BUILD_DIR/android-project-deployment-settings.json --gradle --reinstall --device <adb_device_id>
+ androiddeployqt --input <build_dir>/android-project_name-deployment-settings.json \
+ --output <build_dir>/android-build --install --device <device_serial_id>
\endcode
\section1 Dependencies Detection
@@ -168,11 +59,13 @@
dependencies based on the Qt dependencies of your application. If the plugin
has any Qt dependencies which are not also dependencies of your application,
it will not be included by default. For instance, in order to ensure that
- the SVG image format plugin is included, you will need to add \l{Qt SVG}
+ the SVG image format plugin is included, you will need to add \l {Qt SVG}
module to your project for it to become a dependency of your application:
\badcode
- QT += svg
+ find_package(Qt6 REQUIRED COMPONENTS Svg)
+ ...
+ target_link_libraries(target_name PRIVATE Qt6::Svg)
\endcode
If you are wondering why a particular plugin is not included automatically,
@@ -183,64 +76,20 @@
\uicontrol {Advanced Actions}.
It's also possible to manually specify the dependencies of your application.
- For more information, see \l{ANDROID_DEPLOYMENT_DEPENDENCIES} qmake variable.
-
- \section1 Android-specific qmake Variables
-
- Unless the project has special requirements such as third party libraries,
- it should be possible to run \l androiddeployqt on it with no modifications
- and get a working Qt for Android application.
-
- There are two important environment variables used by Qt:
-
- \list
- \li \c{ANDROID_SDK_ROOT}: specifies the path to the Android SDK used for
- building the application. The Android SDK contains the build-tools,
- Android NDK, and Android toolchains.
- \li \c{ANDROID_NDK_ROOT}: specifies the path to the Android NDK used to
- build the application. It is not recommended to hard-code this path,
- since different Qt for Android versions can depend on different
- Android NDK versions.
- \endlist
-
- \note Qt Creator sets these variables by default.
-
- There are a set of \c qmake or \c CMake variables that can be used to tailor
- your package. At some point during development, you will most likely want
- to look into these variables to customize your application.
-
- Here is a list of some variables that are particularly interesting when
- making Android applications:
-
- \list
- \li \l{ANDROID_PACKAGE_SOURCE_DIR}
- \li \l{ANDROID_VERSION_CODE}
- \li \l{ANDROID_VERSION_NAME}
- \li \l{ANDROID_EXTRA_LIBS}
- \li \l{ANDROID_EXTRA_PLUGINS}
- \li \l{ANDROID_ABIS}
- \li \l{ANDROID_API_VERSION}
- \li \l{ANDROID_DEPLOYMENT_DEPENDENCIES}
- \li \l{ANDROID_MIN_SDK_VERSION}
- \li \l{ANDROID_TARGET_SDK_VERSION}
- \li \l{JAVA_HOME}
- \endlist
-
- Also, the following \c qmake variables are primarily useful when writing a Qt module, and not
- normal applications:
-
- \list
- \li \l{ANDROID_BUNDLED_JAR_DEPENDENCIES}
- \li \l{ANDROID_LIB_DEPENDENCIES}
- \li \l{ANDROID_PERMISSIONS}
- \li \l{ANDROID_FEATURES}
- \endlist
-
- \note This list of variables can also be used with CMake.
+ For more information, see \l {QT_ANDROID_DEPLOYMENT_DEPENDENCIES} CMake variable.
+
+ \note androiddeployqt scans the QML files of the project to collect the QML imports.
+ However, if you are loading QML code as a QString from C++ at runtime, that might
+ not work properly because androiddeployqt won't be aware of it at deploy time.
+ To remedy that, you can add a dummy QML file that imports such QML modules that
+ are referenced at runtime.
\section1 Deployment in Qt Creator
- Qt Creator runs \c androiddeployqt by default, and provides easy
- and intuitive user interfaces to specify many of the options. For more
- information, see \l{Qt Creator: Deploying Applications to Android Devices}.
+ Qt Creator uses \c androiddeployqt under the hood, and provides easy
+ and intuitive user interfaces to specify various options. For more information,
+ see \l{Qt Creator: Deploying Applications to Android Devices}.
+
+ For more information about customizing and deploying a Qt for Android app,
+ see \l {Deploying an Application on Android}.
*/
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 4c79463ebf..6125b405b5 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QCoreApplication>
#include <QStringList>
@@ -38,12 +13,16 @@
#include <QXmlStreamReader>
#include <QStandardPaths>
#include <QUuid>
-#include <QDirIterator>
+#include <QDirListing>
#include <QElapsedTimer>
#include <QRegularExpression>
#include <QSettings>
+#include <QHash>
+#include <QSet>
+#include <QMap>
#include <depfile_shared.h>
+#include <shellquote_shared.h>
#include <algorithm>
@@ -59,6 +38,8 @@
#define QT_POPEN_READ "r"
#endif
+using namespace Qt::StringLiterals;
+
static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output
static QStringList dependenciesForDepfile;
@@ -66,7 +47,7 @@ static QStringList dependenciesForDepfile;
FILE *openProcess(const QString &command)
{
#if defined(Q_OS_WIN32)
- QString processedCommand = QLatin1Char('\"') + command + QLatin1Char('\"');
+ QString processedCommand = u'\"' + command + u'\"';
#else
const QString& processedCommand = command;
#endif
@@ -89,10 +70,18 @@ struct QtDependency
struct QtInstallDirectoryWithTriple
{
- QtInstallDirectoryWithTriple(const QString &dir = QString(), const QString &t = QString()) :
- qtInstallDirectory(dir), triple(t), enabled(false) {}
+ QtInstallDirectoryWithTriple(const QString &dir = QString(),
+ const QString &t = QString(),
+ const QHash<QString, QString> &dirs = QHash<QString, QString>()
+ ) :
+ qtInstallDirectory(dir),
+ qtDirectories(dirs),
+ triple(t),
+ enabled(false)
+ {}
QString qtInstallDirectory;
+ QHash<QString, QString> qtDirectories;
QString triple;
bool enabled;
};
@@ -107,12 +96,11 @@ struct Options
, auxMode(false)
, deploymentMechanism(Bundled)
, releasePackage(false)
- , digestAlg(QLatin1String("SHA-256"))
- , sigAlg(QLatin1String("SHA256withRSA"))
+ , digestAlg("SHA-256"_L1)
+ , sigAlg("SHA256withRSA"_L1)
, internalSf(false)
, sectionsOnly(false)
, protectedAuthenticationPath(false)
- , jarSigner(false)
, installApk(false)
, uninstallApk(false)
, qmlImportScannerBinaryPath()
@@ -120,7 +108,8 @@ struct Options
enum DeploymentMechanism
{
- Bundled
+ Bundled,
+ Unbundled
};
enum TriState {
@@ -147,8 +136,15 @@ struct Options
// Build paths
QString qtInstallDirectory;
+ QHash<QString, QString> qtDirectories;
+ QString qtDataDirectory;
+ QString qtLibsDirectory;
+ QString qtLibExecsDirectory;
+ QString qtPluginsDirectory;
+ QString qtQmlDirectory;
QString qtHostDirectory;
std::vector<QString> extraPrefixDirs;
+ QStringList androidDeployPlugins;
// Unlike 'extraPrefixDirs', the 'extraLibraryDirs' key doesn't expect the 'lib' subfolder
// when looking for dependencies.
std::vector<QString> extraLibraryDirs;
@@ -168,7 +164,7 @@ struct Options
QString versionName;
QString versionCode;
QByteArray minSdkVersion{"23"};
- QByteArray targetSdkVersion{"30"};
+ QByteArray targetSdkVersion{"34"};
// lib c++ path
QString stdCppPath;
@@ -186,6 +182,7 @@ struct Options
// Package information
DeploymentMechanism deploymentMechanism;
+ QString systemLibsPath;
QString packageName;
QStringList extraLibs;
QHash<QString, QStringList> archExtraLibs;
@@ -208,7 +205,6 @@ struct Options
bool internalSf;
bool sectionsOnly;
bool protectedAuthenticationPath;
- bool jarSigner;
QString apkPath;
// Installation information
@@ -217,12 +213,19 @@ struct Options
QString installLocation;
// Per architecture collected information
- void setCurrentQtArchitecture(const QString &arch, const QString &directory)
+ void setCurrentQtArchitecture(const QString &arch,
+ const QString &directory,
+ const QHash<QString, QString> &directories)
{
currentArchitecture = arch;
qtInstallDirectory = directory;
+ qtDataDirectory = directories["qtDataDirectory"_L1];
+ qtLibsDirectory = directories["qtLibsDirectory"_L1];
+ qtLibExecsDirectory = directories["qtLibExecsDirectory"_L1];
+ qtPluginsDirectory = directories["qtPluginsDirectory"_L1];
+ qtQmlDirectory = directories["qtQmlDirectory"_L1];
}
- typedef QPair<QString, QString> BundledFile;
+ using BundledFile = std::pair<QString, QString>;
QHash<QString, QList<BundledFile>> bundledFiles;
QHash<QString, QList<QtDependency>> qtDependencies;
QHash<QString, QStringList> localLibs;
@@ -235,6 +238,7 @@ struct Options
// Override qml import scanner path
QString qmlImportScannerBinaryPath;
+ bool qmlSkipImportScanning = false;
};
static const QHash<QByteArray, QByteArray> elfArchitectures = {
@@ -244,84 +248,52 @@ static const QHash<QByteArray, QByteArray> elfArchitectures = {
{"x86_64", "x86_64"}
};
-// Copy-pasted from qmake/library/ioutil.cpp
-inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
+bool goodToCopy(const Options *options, const QString &file, QStringList *unmetDependencies);
+bool checkCanImportFromRootPaths(const Options *options, const QString &absolutePath,
+ const QString &moduleUrl);
+bool readDependenciesFromElf(Options *options, const QString &fileName,
+ QSet<QString> *usedDependencies, QSet<QString> *remainingDependencies);
+
+QString architectureFromName(const QString &name)
{
- for (int x = arg.length() - 1; x >= 0; --x) {
- ushort c = arg.unicode()[x].unicode();
- if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
- return true;
- }
- return false;
+ QRegularExpression architecture(QStringLiteral("_(armeabi-v7a|arm64-v8a|x86|x86_64).so$"));
+ auto match = architecture.match(name);
+ if (!match.hasMatch())
+ return {};
+ return match.captured(1);
}
-static QString shellQuoteUnix(const QString &arg)
+static QString execSuffixAppended(QString path)
{
- // Chars that should be quoted (TM). This includes:
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
- 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
- }; // 0-32 \'"$`<>|;&(){}*?#!~[]
-
- if (!arg.length())
- return QLatin1String("\"\"");
-
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
- ret.prepend(QLatin1Char('\''));
- ret.append(QLatin1Char('\''));
- }
- return ret;
+#if defined(Q_OS_WIN32)
+ path += ".exe"_L1;
+#endif
+ return path;
}
-static QString shellQuoteWin(const QString &arg)
+static QString batSuffixAppended(QString path)
{
- // Chars that should be quoted (TM). This includes:
- // - control chars & space
- // - the shell meta chars "&()<>^|
- // - the potential separators ,;=
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
- };
-
- if (!arg.length())
- return QLatin1String("\"\"");
-
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- // Quotes are escaped and their preceding backslashes are doubled.
- // It's impossible to escape anything inside a quoted string on cmd
- // level, so the outer quoting must be "suspended".
- ret.replace(QRegularExpression(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
- // The argument must not end with a \ since this would be interpreted
- // as escaping the quote -- rather put the \ behind the quote: e.g.
- // rather use "foo"\ than "foo\"
- int i = ret.length();
- while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
- --i;
- ret.insert(i, QLatin1Char('"'));
- ret.prepend(QLatin1Char('"'));
- }
- return ret;
+#if defined(Q_OS_WIN32)
+ path += ".bat"_L1;
+#endif
+ return path;
}
-static QString shellQuote(const QString &arg)
+QString defaultLibexecDir()
{
- if (QDir::separator() == QLatin1Char('\\'))
- return shellQuoteWin(arg);
- else
- return shellQuoteUnix(arg);
+#ifdef Q_OS_WIN32
+ return "bin"_L1;
+#else
+ return "libexec"_L1;
+#endif
}
-QString architectureFromName(const QString &name)
+static QString llvmReadobjPath(const Options &options)
{
- QRegularExpression architecture(QStringLiteral("_(armeabi-v7a|arm64-v8a|x86|x86_64).so$"));
- auto match = architecture.match(name);
- if (!match.hasMatch())
- return {};
- return match.captured(1);
+ return execSuffixAppended("%1/toolchains/%2/prebuilt/%3/bin/llvm-readobj"_L1
+ .arg(options.ndkPath,
+ options.toolchainPrefix,
+ options.ndkHost));
}
QString fileArchitecture(const Options &options, const QString &path)
@@ -330,19 +302,13 @@ QString fileArchitecture(const Options &options, const QString &path)
if (!arch.isEmpty())
return arch;
- QString readElf = QLatin1String("%1/toolchains/%2/prebuilt/%3/bin/llvm-readobj").arg(options.ndkPath,
- options.toolchainPrefix,
- options.ndkHost);
-#if defined(Q_OS_WIN32)
- readElf += QLatin1String(".exe");
-#endif
-
+ QString readElf = llvmReadobjPath(options);
if (!QFile::exists(readElf)) {
fprintf(stderr, "Command does not exist: %s\n", qPrintable(readElf));
return {};
}
- readElf = QLatin1String("%1 -needed-libs %2").arg(shellQuote(readElf), shellQuote(path));
+ readElf = "%1 --needed-libs %2"_L1.arg(shellQuote(readElf), shellQuote(path));
FILE *readElfCommand = openProcess(readElf);
if (!readElfCommand) {
@@ -353,7 +319,6 @@ QString fileArchitecture(const Options &options, const QString &path)
char buffer[512];
while (fgets(buffer, sizeof(buffer), readElfCommand) != nullptr) {
QByteArray line = QByteArray::fromRawData(buffer, qstrlen(buffer));
- QString library;
line = line.trimmed();
if (line.startsWith("Arch: ")) {
auto it = elfArchitectures.find(line.mid(6));
@@ -382,7 +347,7 @@ void deleteMissingFiles(const Options &options, const QDir &srcDir, const QDir &
for (const QFileInfo &src : srcEntries)
if (dst.fileName() == src.fileName()) {
if (dst.isDir())
- deleteMissingFiles(options, src.absoluteDir(), dst.absoluteDir());
+ deleteMissingFiles(options, src.absoluteFilePath(), dst.absoluteFilePath());
found = true;
break;
}
@@ -400,7 +365,6 @@ void deleteMissingFiles(const Options &options, const QDir &srcDir, const QDir &
fflush(stdout);
}
-
Options parseOptions()
{
Options options;
@@ -408,94 +372,100 @@ Options parseOptions()
QStringList arguments = QCoreApplication::arguments();
for (int i=0; i<arguments.size(); ++i) {
const QString &argument = arguments.at(i);
- if (argument.compare(QLatin1String("--output"), Qt::CaseInsensitive) == 0) {
+ if (argument.compare("--output"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.outputDirectory = arguments.at(++i).trimmed();
- } else if (argument.compare(QLatin1String("--input"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--input"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.inputFileName = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--aab"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--aab"_L1, Qt::CaseInsensitive) == 0) {
options.buildAAB = true;
options.build = true;
- options.jarSigner = true;
- } else if (!options.buildAAB && argument.compare(QLatin1String("--no-build"), Qt::CaseInsensitive) == 0) {
+ } else if (!options.buildAAB && argument.compare("--no-build"_L1, Qt::CaseInsensitive) == 0) {
options.build = false;
- } else if (argument.compare(QLatin1String("--install"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--install"_L1, Qt::CaseInsensitive) == 0) {
options.installApk = true;
options.uninstallApk = true;
- } else if (argument.compare(QLatin1String("--reinstall"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--reinstall"_L1, Qt::CaseInsensitive) == 0) {
options.installApk = true;
options.uninstallApk = false;
- } else if (argument.compare(QLatin1String("--android-platform"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--android-platform"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.androidPlatform = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--help"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--help"_L1, Qt::CaseInsensitive) == 0) {
options.helpRequested = true;
- } else if (argument.compare(QLatin1String("--verbose"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--verbose"_L1, Qt::CaseInsensitive) == 0) {
options.verbose = true;
- } else if (argument.compare(QLatin1String("--deployment"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--deployment"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size()) {
options.helpRequested = true;
} else {
QString deploymentMechanism = arguments.at(++i);
- if (deploymentMechanism.compare(QLatin1String("bundled"), Qt::CaseInsensitive) == 0) {
+ if (deploymentMechanism.compare("bundled"_L1, Qt::CaseInsensitive) == 0) {
options.deploymentMechanism = Options::Bundled;
+ } else if (deploymentMechanism.compare("unbundled"_L1,
+ Qt::CaseInsensitive) == 0) {
+ options.deploymentMechanism = Options::Unbundled;
} else {
fprintf(stderr, "Unrecognized deployment mechanism: %s\n", qPrintable(deploymentMechanism));
options.helpRequested = true;
}
}
- } else if (argument.compare(QLatin1String("--device"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--device"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.installLocation = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--release"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--release"_L1, Qt::CaseInsensitive) == 0) {
options.releasePackage = true;
- } else if (argument.compare(QLatin1String("--jdk"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--jdk"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.jdkPath = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--apk"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--apk"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.apkPath = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--depfile"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--depfile"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.depFilePath = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--builddir"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--builddir"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.buildDirectory = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--sign"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--sign"_L1, Qt::CaseInsensitive) == 0) {
if (i + 2 >= arguments.size()) {
const QString keyStore = qEnvironmentVariable("QT_ANDROID_KEYSTORE_PATH");
const QString storeAlias = qEnvironmentVariable("QT_ANDROID_KEYSTORE_ALIAS");
if (keyStore.isEmpty() || storeAlias.isEmpty()) {
options.helpRequested = true;
+ fprintf(stderr, "Package signing path and alias values are not specified.\n");
} else {
fprintf(stdout,
"Using package signing path and alias values found from the "
"environment variables.\n");
- options.releasePackage = true;
options.keyStore = keyStore;
options.keyStoreAlias = storeAlias;
}
- } else {
- options.releasePackage = true;
+ } else if (!arguments.at(i + 1).startsWith("--"_L1) &&
+ !arguments.at(i + 2).startsWith("--"_L1)) {
options.keyStore = arguments.at(++i);
options.keyStoreAlias = arguments.at(++i);
+ } else {
+ options.helpRequested = true;
+ fprintf(stderr, "Package signing path and alias values are not "
+ "specified.\n");
}
// Do not override if the passwords are provided through arguments
@@ -509,62 +479,60 @@ Options parseOptions()
"variable.\n");
options.keyPass = qEnvironmentVariable("QT_ANDROID_KEYSTORE_KEY_PASS");
}
- } else if (argument.compare(QLatin1String("--storepass"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--storepass"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.keyStorePassword = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--storetype"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--storetype"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.storeType = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--keypass"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--keypass"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.keyPass = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--sigfile"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--sigfile"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.sigFile = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--digestalg"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--digestalg"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.digestAlg = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--sigalg"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--sigalg"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.sigAlg = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--tsa"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--tsa"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.tsaUrl = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--tsacert"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--tsacert"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
else
options.tsaCert = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--internalsf"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--internalsf"_L1, Qt::CaseInsensitive) == 0) {
options.internalSf = true;
- } else if (argument.compare(QLatin1String("--sectionsonly"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--sectionsonly"_L1, Qt::CaseInsensitive) == 0) {
options.sectionsOnly = true;
- } else if (argument.compare(QLatin1String("--protected"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--protected"_L1, Qt::CaseInsensitive) == 0) {
options.protectedAuthenticationPath = true;
- } else if (argument.compare(QLatin1String("--jarsigner"), Qt::CaseInsensitive) == 0) {
- options.jarSigner = true;
- } else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--aux-mode"_L1, Qt::CaseInsensitive) == 0) {
options.auxMode = true;
- } else if (argument.compare(QLatin1String("--qml-importscanner-binary"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--qml-importscanner-binary"_L1, Qt::CaseInsensitive) == 0) {
options.qmlImportScannerBinaryPath = arguments.at(++i).trimmed();
- } else if (argument.compare(QLatin1String("--no-rcc-bundle-cleanup"),
+ } else if (argument.compare("--no-rcc-bundle-cleanup"_L1,
Qt::CaseInsensitive) == 0) {
options.noRccBundleCleanup = true;
- } else if (argument.compare(QLatin1String("--copy-dependencies-only"),
+ } else if (argument.compare("--copy-dependencies-only"_L1,
Qt::CaseInsensitive) == 0) {
options.copyDependenciesOnly = true;
}
@@ -574,7 +542,7 @@ Options parseOptions()
options.helpRequested = true;
if (options.inputFileName.isEmpty())
- options.inputFileName = QLatin1String("android-%1-deployment-settings.json").arg(QDir::current().dirName());
+ options.inputFileName = "android-%1-deployment-settings.json"_L1.arg(QDir::current().dirName());
options.timing = qEnvironmentVariableIsSet("ANDROIDDEPLOYQT_TIMING_OUTPUT");
@@ -583,121 +551,121 @@ Options parseOptions()
options.outputDirectory.clear();
} else {
options.outputDirectory = QFileInfo(options.outputDirectory).canonicalFilePath();
- if (!options.outputDirectory.endsWith(QLatin1Char('/')))
- options.outputDirectory += QLatin1Char('/');
+ if (!options.outputDirectory.endsWith(u'/'))
+ options.outputDirectory += u'/';
}
return options;
}
void printHelp()
-{// "012345678901234567890123456789012345678901234567890123456789012345678901"
- fprintf(stderr, "Syntax: %s --output <destination> [options]\n"
- "\n"
- " Creates an Android package in the build directory <destination> and\n"
- " builds it into an .apk file.\n"
- "\n"
- " Optional arguments:\n"
- " --input <inputfile>: Reads <inputfile> for options generated by\n"
- " qmake. A default file name based on the current working\n"
- " directory will be used if nothing else is specified.\n"
- "\n"
- " --deployment <mechanism>: Supported deployment mechanisms:\n"
- " bundled (default): Include Qt files in stand-alone package.\n"
- "\n"
- " --aab: Build an Android App Bundle.\n"
- "\n"
- " --no-build: Do not build the package, it is useful to just install\n"
- " a package previously built.\n"
- "\n"
- " --install: Installs apk to device/emulator. By default this step is\n"
- " not taken. If the application has previously been installed on\n"
- " the device, it will be uninstalled first.\n"
- "\n"
- " --reinstall: Installs apk to device/emulator. By default this step\n"
- " is not taken. If the application has previously been installed on\n"
- " the device, it will be overwritten, but its data will be left\n"
- " intact.\n"
- "\n"
- " --device [device ID]: Use specified device for deployment. Default\n"
- " is the device selected by default by adb.\n"
- "\n"
- " --android-platform <platform>: Builds against the given android\n"
- " platform. By default, the highest available version will be\n"
- " used.\n"
- "\n"
- " --release: Builds a package ready for release. By default, the\n"
- " package will be signed with a debug key.\n"
- "\n"
- " --sign <url/to/keystore> <alias>: Signs the package with the\n"
- " specified keystore, alias and store password. Also implies the\n"
- " --release option.\n"
- " Optional arguments for use with signing:\n"
- " --storepass <password>: Keystore password.\n"
- " --storetype <type>: Keystore type.\n"
- " --keypass <password>: Password for private key (if different\n"
- " from keystore password.)\n"
- " --sigfile <file>: Name of .SF/.DSA file.\n"
- " --digestalg <name>: Name of digest algorithm. Default is\n"
- " \"SHA1\".\n"
- " --sigalg <name>: Name of signature algorithm. Default is\n"
- " \"SHA1withRSA\".\n"
- " --tsa <url>: Location of the Time Stamping Authority.\n"
- " --tsacert <alias>: Public key certificate for TSA.\n"
- " --internalsf: Include the .SF file inside the signature block.\n"
- " --sectionsonly: Don't compute hash of entire manifest.\n"
- " --protected: Keystore has protected authentication path.\n"
- " --jarsigner: Force jarsigner usage, otherwise apksigner will be\n"
- " used if available.\n"
- "\n"
- " NOTE: To conceal the keystore information, the environment variables\n"
- " QT_ANDROID_KEYSTORE_PATH, and QT_ANDROID_KEYSTORE_ALIAS are used to\n"
- " set the values keysotore and alias respectively.\n"
- " Also the environment variables QT_ANDROID_KEYSTORE_STORE_PASS,\n"
- " and QT_ANDROID_KEYSTORE_KEY_PASS are used to set the store and key\n"
- " passwords respectively. This option needs only the --sign parameter.\n"
- "\n"
- " --jdk <path/to/jdk>: Used to find the jarsigner tool when used\n"
- " in combination with the --release argument. By default,\n"
- " an attempt is made to detect the tool using the JAVA_HOME and\n"
- " PATH environment variables, in that order.\n"
- "\n"
- " --qml-import-paths: Specify additional search paths for QML\n"
- " imports.\n"
- "\n"
- " --verbose: Prints out information during processing.\n"
- "\n"
- " --no-generated-assets-cache: Do not pregenerate the entry list for\n"
- " the assets file engine.\n"
- "\n"
- " --aux-mode: Operate in auxiliary mode. This will only copy the\n"
- " dependencies into the build directory and update the XML templates.\n"
- " The project will not be built or installed.\n"
- "\n"
- " --apk <path/where/to/copy/the/apk>: Path where to copy the built apk.\n"
- "\n"
- " --qml-importscanner-binary <path/to/qmlimportscanner>: Override the\n"
- " default qmlimportscanner binary path. By default the\n"
- " qmlimportscanner binary is located using the Qt directory\n"
- " specified in the input file.\n"
- "\n"
- " --depfile <path/to/depfile>: Output a dependency file.\n"
- "\n"
- " --builddir <path/to/build/directory>: build directory. Necessary when\n"
- " generating a depfile because ninja requires relative paths.\n"
- "\n"
- " --no-rcc-bundle-cleanup: skip cleaning rcc bundle directory after\n"
- " running androiddeployqt. This option simplifies debugging of\n"
- " the resource bundle content, but it should not be used when deploying\n"
- " a project, since it litters the 'assets' directory.\n"
- "\n"
- " --copy-dependencies-only: resolve application dependencies and stop\n"
- " deploying process after all libraries and resources that the\n"
- " application depends on have been copied.\n"
- "\n"
- " --help: Displays this information.\n",
- qPrintable(QCoreApplication::arguments().at(0))
- );
+{
+ fprintf(stderr, R"(
+Syntax: androiddeployqt --output <destination> [options]
+
+Creates an Android package in the build directory <destination> and
+builds it into an .apk file.
+
+Optional arguments:
+ --input <inputfile>: Reads <inputfile> for options generated by
+ qmake. A default file name based on the current working
+ directory will be used if nothing else is specified.
+
+ --deployment <mechanism>: Supported deployment mechanisms:
+ bundled (default): Includes Qt files in stand-alone package.
+ unbundled: Assumes native libraries are present on the device
+ and does not include them in the APK.
+
+ --aab: Build an Android App Bundle.
+
+ --no-build: Do not build the package, it is useful to just install
+ a package previously built.
+
+ --install: Installs apk to device/emulator. By default this step is
+ not taken. If the application has previously been installed on
+ the device, it will be uninstalled first.
+
+ --reinstall: Installs apk to device/emulator. By default this step
+ is not taken. If the application has previously been installed on
+ the device, it will be overwritten, but its data will be left
+ intact.
+
+ --device [device ID]: Use specified device for deployment. Default
+ is the device selected by default by adb.
+
+ --android-platform <platform>: Builds against the given android
+ platform. By default, the highest available version will be
+ used.
+
+ --release: Builds a package ready for release. By default, the
+ package will be signed with a debug key.
+
+ --sign <url/to/keystore> <alias>: Signs the package with the
+ specified keystore, alias and store password.
+ Optional arguments for use with signing:
+ --storepass <password>: Keystore password.
+ --storetype <type>: Keystore type.
+ --keypass <password>: Password for private key (if different
+ from keystore password.)
+ --sigfile <file>: Name of .SF/.DSA file.
+ --digestalg <name>: Name of digest algorithm. Default is
+ "SHA-256".
+ --sigalg <name>: Name of signature algorithm. Default is
+ "SHA256withRSA".
+ --tsa <url>: Location of the Time Stamping Authority.
+ --tsacert <alias>: Public key certificate for TSA.
+ --internalsf: Include the .SF file inside the signature block.
+ --sectionsonly: Don't compute hash of entire manifest.
+ --protected: Keystore has protected authentication path.
+ --jarsigner: Deprecated, ignored.
+
+ NOTE: To conceal the keystore information, the environment variables
+ QT_ANDROID_KEYSTORE_PATH, and QT_ANDROID_KEYSTORE_ALIAS are used to
+ set the values keysotore and alias respectively.
+ Also the environment variables QT_ANDROID_KEYSTORE_STORE_PASS,
+ and QT_ANDROID_KEYSTORE_KEY_PASS are used to set the store and key
+ passwords respectively. This option needs only the --sign parameter.
+
+ --jdk <path/to/jdk>: Used to find the jarsigner tool when used
+ in combination with the --release argument. By default,
+ an attempt is made to detect the tool using the JAVA_HOME and
+ PATH environment variables, in that order.
+
+ --qml-import-paths: Specify additional search paths for QML
+ imports.
+
+ --verbose: Prints out information during processing.
+
+ --no-generated-assets-cache: Do not pregenerate the entry list for
+ the assets file engine.
+
+ --aux-mode: Operate in auxiliary mode. This will only copy the
+ dependencies into the build directory and update the XML templates.
+ The project will not be built or installed.
+
+ --apk <path/where/to/copy/the/apk>: Path where to copy the built apk.
+
+ --qml-importscanner-binary <path/to/qmlimportscanner>: Override the
+ default qmlimportscanner binary path. By default the
+ qmlimportscanner binary is located using the Qt directory
+ specified in the input file.
+
+ --depfile <path/to/depfile>: Output a dependency file.
+
+ --builddir <path/to/build/directory>: build directory. Necessary when
+ generating a depfile because ninja requires relative paths.
+
+ --no-rcc-bundle-cleanup: skip cleaning rcc bundle directory after
+ running androiddeployqt. This option simplifies debugging of
+ the resource bundle content, but it should not be used when deploying
+ a project, since it litters the 'assets' directory.
+
+ --copy-dependencies-only: resolve application dependencies and stop
+ deploying process after all libraries and resources that the
+ application depends on have been copied.
+
+ --help: Displays this information.
+)");
}
// Since strings compared will all start with the same letters,
@@ -708,20 +676,20 @@ bool quasiLexicographicalReverseLessThan(const QFileInfo &fi1, const QFileInfo &
QString s1 = fi1.baseName();
QString s2 = fi2.baseName();
- if (s1.length() == s2.length())
+ if (s1.size() == s2.size())
return s1 > s2;
else
- return s1.length() > s2.length();
+ return s1.size() > s2.size();
}
// Files which contain templates that need to be overwritten by build data should be overwritten every
// time.
bool alwaysOverwritableFile(const QString &fileName)
{
- return (fileName.endsWith(QLatin1String("/res/values/libs.xml"))
- || fileName.endsWith(QLatin1String("/AndroidManifest.xml"))
- || fileName.endsWith(QLatin1String("/res/values/strings.xml"))
- || fileName.endsWith(QLatin1String("/src/org/qtproject/qt/android/bindings/QtActivity.java")));
+ return (fileName.endsWith("/res/values/libs.xml"_L1)
+ || fileName.endsWith("/AndroidManifest.xml"_L1)
+ || fileName.endsWith("/res/values/strings.xml"_L1)
+ || fileName.endsWith("/src/org/qtproject/qt/android/bindings/QtActivity.java"_L1));
}
@@ -775,48 +743,47 @@ QString cleanPackageName(QString packageName)
};
for (QChar &c : packageName) {
if (!isLegalChar(c))
- c = QLatin1Char('_');
+ c = u'_';
}
static QStringList keywords;
if (keywords.isEmpty()) {
- keywords << QLatin1String("abstract") << QLatin1String("continue") << QLatin1String("for")
- << QLatin1String("new") << QLatin1String("switch") << QLatin1String("assert")
- << QLatin1String("default") << QLatin1String("if") << QLatin1String("package")
- << QLatin1String("synchronized") << QLatin1String("boolean") << QLatin1String("do")
- << QLatin1String("goto") << QLatin1String("private") << QLatin1String("this")
- << QLatin1String("break") << QLatin1String("double") << QLatin1String("implements")
- << QLatin1String("protected") << QLatin1String("throw") << QLatin1String("byte")
- << QLatin1String("else") << QLatin1String("import") << QLatin1String("public")
- << QLatin1String("throws") << QLatin1String("case") << QLatin1String("enum")
- << QLatin1String("instanceof") << QLatin1String("return") << QLatin1String("transient")
- << QLatin1String("catch") << QLatin1String("extends") << QLatin1String("int")
- << QLatin1String("short") << QLatin1String("try") << QLatin1String("char")
- << QLatin1String("final") << QLatin1String("interface") << QLatin1String("static")
- << QLatin1String("void") << QLatin1String("class") << QLatin1String("finally")
- << QLatin1String("long") << QLatin1String("strictfp") << QLatin1String("volatile")
- << QLatin1String("const") << QLatin1String("float") << QLatin1String("native")
- << QLatin1String("super") << QLatin1String("while");
+ keywords << "abstract"_L1 << "continue"_L1 << "for"_L1
+ << "new"_L1 << "switch"_L1 << "assert"_L1
+ << "default"_L1 << "if"_L1 << "package"_L1
+ << "synchronized"_L1 << "boolean"_L1 << "do"_L1
+ << "goto"_L1 << "private"_L1 << "this"_L1
+ << "break"_L1 << "double"_L1 << "implements"_L1
+ << "protected"_L1 << "throw"_L1 << "byte"_L1
+ << "else"_L1 << "import"_L1 << "public"_L1
+ << "throws"_L1 << "case"_L1 << "enum"_L1
+ << "instanceof"_L1 << "return"_L1 << "transient"_L1
+ << "catch"_L1 << "extends"_L1 << "int"_L1
+ << "short"_L1 << "try"_L1 << "char"_L1
+ << "final"_L1 << "interface"_L1 << "static"_L1
+ << "void"_L1 << "class"_L1 << "finally"_L1
+ << "long"_L1 << "strictfp"_L1 << "volatile"_L1
+ << "const"_L1 << "float"_L1 << "native"_L1
+ << "super"_L1 << "while"_L1;
}
// No keywords
- int index = -1;
- while (index < packageName.length()) {
- int next = packageName.indexOf(QLatin1Char('.'), index + 1);
+ qsizetype index = -1;
+ while (index < packageName.size()) {
+ qsizetype next = packageName.indexOf(u'.', index + 1);
if (next == -1)
- next = packageName.length();
+ next = packageName.size();
QString word = packageName.mid(index + 1, next - index - 1);
if (!word.isEmpty()) {
QChar c = word[0];
- if ((c >= QChar(QLatin1Char('0')) && c<= QChar(QLatin1Char('9')))
- || c == QLatin1Char('_')) {
- packageName.insert(index + 1, QLatin1Char('a'));
+ if ((c >= u'0' && c <= u'9') || c == u'_') {
+ packageName.insert(index + 1, u'a');
index = next + 1;
continue;
}
}
if (keywords.contains(word)) {
- packageName.insert(next, QLatin1String("_"));
+ packageName.insert(next, "_"_L1);
index = next + 1;
} else {
index = next;
@@ -828,7 +795,7 @@ QString cleanPackageName(QString packageName)
QString detectLatestAndroidPlatform(const QString &sdkPath)
{
- QDir dir(sdkPath + QLatin1String("/platforms"));
+ QDir dir(sdkPath + "/platforms"_L1);
if (!dir.exists()) {
fprintf(stderr, "Directory %s does not exist\n", qPrintable(dir.absolutePath()));
return QString();
@@ -842,7 +809,7 @@ QString detectLatestAndroidPlatform(const QString &sdkPath)
std::sort(fileInfos.begin(), fileInfos.end(), quasiLexicographicalReverseLessThan);
- QFileInfo latestPlatform = fileInfos.first();
+ const QFileInfo& latestPlatform = fileInfos.constFirst();
return latestPlatform.baseName();
}
@@ -853,14 +820,83 @@ QString packageNameFromAndroidManifest(const QString &androidManifestPath)
QXmlStreamReader reader(&androidManifestXml);
while (!reader.atEnd()) {
reader.readNext();
- if (reader.isStartElement() && reader.name() == QLatin1String("manifest"))
- return cleanPackageName(
- reader.attributes().value(QLatin1String("package")).toString());
+ if (reader.isStartElement() && reader.name() == "manifest"_L1)
+ return cleanPackageName(reader.attributes().value("package"_L1).toString());
}
}
return {};
}
+bool parseCmakeBoolean(const QJsonValue &value)
+{
+ const QString stringValue = value.toString();
+ return (stringValue.compare(QString::fromUtf8("true"), Qt::CaseInsensitive)
+ || stringValue.compare(QString::fromUtf8("on"), Qt::CaseInsensitive)
+ || stringValue.compare(QString::fromUtf8("yes"), Qt::CaseInsensitive)
+ || stringValue.compare(QString::fromUtf8("y"), Qt::CaseInsensitive)
+ || stringValue.toInt() > 0);
+}
+
+bool readInputFileDirectory(Options *options, QJsonObject &jsonObject, const QString keyName)
+{
+ const QJsonValue qtDirectory = jsonObject.value(keyName);
+ if (qtDirectory.isUndefined()) {
+ for (auto it = options->architectures.constBegin(); it != options->architectures.constEnd(); ++it) {
+ if (keyName == "qtDataDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "."_L1;
+ break;
+ } else if (keyName == "qtLibsDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "lib"_L1;
+ break;
+ } else if (keyName == "qtLibExecsDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = defaultLibexecDir();
+ break;
+ } else if (keyName == "qtPluginsDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "plugins"_L1;
+ break;
+ } else if (keyName == "qtQmlDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "qml"_L1;
+ break;
+ }
+ }
+ return true;
+ }
+
+ if (qtDirectory.isObject()) {
+ const QJsonObject object = qtDirectory.toObject();
+ for (auto it = object.constBegin(); it != object.constEnd(); ++it) {
+ if (it.value().isUndefined()) {
+ fprintf(stderr,
+ "Invalid '%s' record in deployment settings: %s\n",
+ qPrintable(keyName),
+ qPrintable(it.value().toString()));
+ return false;
+ }
+ if (it.value().isNull())
+ continue;
+ if (!options->architectures.contains(it.key())) {
+ fprintf(stderr, "Architecture %s unknown (%s).", qPrintable(it.key()),
+ qPrintable(options->architectures.keys().join(u',')));
+ return false;
+ }
+ options->architectures[it.key()].qtDirectories[keyName] = it.value().toString();
+ }
+ } else if (qtDirectory.isString()) {
+ // Format for Qt < 6 or when using the tool with Qt >= 6 but in single arch.
+ // We assume Qt > 5.14 where all architectures are in the same directory.
+ const QString directory = qtDirectory.toString();
+ options->architectures["arm64-v8a"_L1].qtDirectories[keyName] = directory;
+ options->architectures["armeabi-v7a"_L1].qtDirectories[keyName] = directory;
+ options->architectures["x86"_L1].qtDirectories[keyName] = directory;
+ options->architectures["x86_64"_L1].qtDirectories[keyName] = directory;
+ } else {
+ fprintf(stderr, "Invalid format for %s in json file %s.\n",
+ qPrintable(keyName), qPrintable(options->inputFileName));
+ return false;
+ }
+ return true;
+}
+
bool readInputFile(Options *options)
{
QFile file(options->inputFileName);
@@ -879,7 +915,7 @@ bool readInputFile(Options *options)
QJsonObject jsonObject = jsonDocument.object();
{
- QJsonValue sdkPath = jsonObject.value(QLatin1String("sdk"));
+ QJsonValue sdkPath = jsonObject.value("sdk"_L1);
if (sdkPath.isUndefined()) {
fprintf(stderr, "No SDK path in json file %s\n", qPrintable(options->inputFileName));
return false;
@@ -892,7 +928,7 @@ bool readInputFile(Options *options)
if (options->androidPlatform.isEmpty())
return false;
} else {
- if (!QDir(options->sdkPath + QLatin1String("/platforms/") + options->androidPlatform).exists()) {
+ if (!QDir(options->sdkPath + "/platforms/"_L1 + options->androidPlatform).exists()) {
fprintf(stderr, "Warning: Android platform '%s' does not exist in SDK.\n",
qPrintable(options->androidPlatform));
}
@@ -901,13 +937,13 @@ bool readInputFile(Options *options)
{
- const QJsonValue value = jsonObject.value(QLatin1String("sdkBuildToolsRevision"));
+ const QJsonValue value = jsonObject.value("sdkBuildToolsRevision"_L1);
if (!value.isUndefined())
options->sdkBuildToolsVersion = value.toString();
}
{
- const QJsonValue qtInstallDirectory = jsonObject.value(QLatin1String("qt"));
+ const QJsonValue qtInstallDirectory = jsonObject.value("qt"_L1);
if (qtInstallDirectory.isUndefined()) {
fprintf(stderr, "No Qt directory in json file %s\n", qPrintable(options->inputFileName));
return false;
@@ -917,7 +953,8 @@ bool readInputFile(Options *options)
const QJsonObject object = qtInstallDirectory.toObject();
for (auto it = object.constBegin(); it != object.constEnd(); ++it) {
if (it.value().isUndefined()) {
- fprintf(stderr, "Invalid architecture: %s\n",
+ fprintf(stderr,
+ "Invalid 'qt' record in deployment settings: %s\n",
qPrintable(it.value().toString()));
return false;
}
@@ -931,10 +968,10 @@ bool readInputFile(Options *options)
// We assume Qt > 5.14 where all architectures are in the same directory.
const QString directory = qtInstallDirectory.toString();
QtInstallDirectoryWithTriple qtInstallDirectoryWithTriple(directory);
- options->architectures.insert(QLatin1String("arm64-v8a"), qtInstallDirectoryWithTriple);
- options->architectures.insert(QLatin1String("armeabi-v7a"), qtInstallDirectoryWithTriple);
- options->architectures.insert(QLatin1String("x86"), qtInstallDirectoryWithTriple);
- options->architectures.insert(QLatin1String("x86_64"), qtInstallDirectoryWithTriple);
+ options->architectures.insert("arm64-v8a"_L1, qtInstallDirectoryWithTriple);
+ options->architectures.insert("armeabi-v7a"_L1, qtInstallDirectoryWithTriple);
+ options->architectures.insert("x86"_L1, qtInstallDirectoryWithTriple);
+ options->architectures.insert("x86_64"_L1, qtInstallDirectoryWithTriple);
// In Qt < 6 rcc and qmlimportscanner are installed in the host and install directories
// In Qt >= 6 rcc and qmlimportscanner are only installed in the host directory
// So setting the "qtHostDir" is not necessary with Qt < 6.
@@ -945,8 +982,16 @@ bool readInputFile(Options *options)
return false;
}
}
+
+ if (!readInputFileDirectory(options, jsonObject, "qtDataDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtLibsDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtLibExecsDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtPluginsDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtQmlDirectory"_L1))
+ return false;
+
{
- const QJsonValue qtHostDirectory = jsonObject.value(QLatin1String("qtHostDir"));
+ const QJsonValue qtHostDirectory = jsonObject.value("qtHostDir"_L1);
if (!qtHostDirectory.isUndefined()) {
if (qtHostDirectory.isString()) {
options->qtHostDirectory = qtHostDirectory.toString();
@@ -959,7 +1004,7 @@ bool readInputFile(Options *options)
}
{
- const auto extraPrefixDirs = jsonObject.value(QLatin1String("extraPrefixDirs")).toArray();
+ const auto extraPrefixDirs = jsonObject.value("extraPrefixDirs"_L1).toArray();
options->extraPrefixDirs.reserve(extraPrefixDirs.size());
for (const QJsonValue prefix : extraPrefixDirs) {
options->extraPrefixDirs.push_back(prefix.toString());
@@ -967,7 +1012,12 @@ bool readInputFile(Options *options)
}
{
- const auto extraLibraryDirs = jsonObject.value(QLatin1String("extraLibraryDirs")).toArray();
+ const auto androidDeployPlugins = jsonObject.value("android-deploy-plugins"_L1).toString();
+ options->androidDeployPlugins = androidDeployPlugins.split(";"_L1, Qt::SkipEmptyParts);
+ }
+
+ {
+ const auto extraLibraryDirs = jsonObject.value("extraLibraryDirs"_L1).toArray();
options->extraLibraryDirs.reserve(extraLibraryDirs.size());
for (const QJsonValue path : extraLibraryDirs) {
options->extraLibraryDirs.push_back(path.toString());
@@ -975,13 +1025,13 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue androidSourcesDirectory = jsonObject.value(QLatin1String("android-package-source-directory"));
+ const QJsonValue androidSourcesDirectory = jsonObject.value("android-package-source-directory"_L1);
if (!androidSourcesDirectory.isUndefined())
options->androidSourceDirectory = androidSourcesDirectory.toString();
}
{
- const QJsonValue applicationArguments = jsonObject.value(QLatin1String("android-application-arguments"));
+ const QJsonValue applicationArguments = jsonObject.value("android-application-arguments"_L1);
if (!applicationArguments.isUndefined())
options->applicationArguments = applicationArguments.toString();
else
@@ -989,7 +1039,7 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue androidVersionName = jsonObject.value(QLatin1String("android-version-name"));
+ const QJsonValue androidVersionName = jsonObject.value("android-version-name"_L1);
if (!androidVersionName.isUndefined())
options->versionName = androidVersionName.toString();
else
@@ -997,7 +1047,7 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue androidVersionCode = jsonObject.value(QLatin1String("android-version-code"));
+ const QJsonValue androidVersionCode = jsonObject.value("android-version-code"_L1);
if (!androidVersionCode.isUndefined())
options->versionCode = androidVersionCode.toString();
else
@@ -1005,19 +1055,19 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue ver = jsonObject.value(QLatin1String("android-min-sdk-version"));
+ const QJsonValue ver = jsonObject.value("android-min-sdk-version"_L1);
if (!ver.isUndefined())
options->minSdkVersion = ver.toString().toUtf8();
}
{
- const QJsonValue ver = jsonObject.value(QLatin1String("android-target-sdk-version"));
+ const QJsonValue ver = jsonObject.value("android-target-sdk-version"_L1);
if (!ver.isUndefined())
options->targetSdkVersion = ver.toString().toUtf8();
}
{
- const QJsonObject targetArchitectures = jsonObject.value(QLatin1String("architectures")).toObject();
+ const QJsonObject targetArchitectures = jsonObject.value("architectures"_L1).toObject();
if (targetArchitectures.isEmpty()) {
fprintf(stderr, "No target architecture defined in json file.\n");
return false;
@@ -1031,7 +1081,7 @@ bool readInputFile(Options *options)
continue;
if (!options->architectures.contains(it.key())) {
fprintf(stderr, "Architecture %s unknown (%s).", qPrintable(it.key()),
- qPrintable(options->architectures.keys().join(QLatin1Char(','))));
+ qPrintable(options->architectures.keys().join(u',')));
return false;
}
options->architectures[it.key()].triple = it.value().toString();
@@ -1040,7 +1090,7 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue ndk = jsonObject.value(QLatin1String("ndk"));
+ const QJsonValue ndk = jsonObject.value("ndk"_L1);
if (ndk.isUndefined()) {
fprintf(stderr, "No NDK path defined in json file.\n");
return false;
@@ -1058,7 +1108,7 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue toolchainPrefix = jsonObject.value(QLatin1String("toolchain-prefix"));
+ const QJsonValue toolchainPrefix = jsonObject.value("toolchain-prefix"_L1);
if (toolchainPrefix.isUndefined()) {
fprintf(stderr, "No toolchain prefix defined in json file.\n");
return false;
@@ -1067,7 +1117,7 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue ndkHost = jsonObject.value(QLatin1String("ndk-host"));
+ const QJsonValue ndkHost = jsonObject.value("ndk-host"_L1);
if (ndkHost.isUndefined()) {
fprintf(stderr, "No NDK host defined in json file.\n");
return false;
@@ -1076,19 +1126,41 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue extraLibs = jsonObject.value(QLatin1String("android-extra-libs"));
+ const QJsonValue extraLibs = jsonObject.value("android-extra-libs"_L1);
if (!extraLibs.isUndefined())
- options->extraLibs = extraLibs.toString().split(QLatin1Char(','), Qt::SkipEmptyParts);
+ options->extraLibs = extraLibs.toString().split(u',', Qt::SkipEmptyParts);
}
{
- const QJsonValue extraPlugins = jsonObject.value(QLatin1String("android-extra-plugins"));
+ const QJsonValue qmlSkipImportScanning = jsonObject.value("qml-skip-import-scanning"_L1);
+ if (!qmlSkipImportScanning.isUndefined())
+ options->qmlSkipImportScanning = qmlSkipImportScanning.toBool();
+ }
+
+ {
+ const QJsonValue extraPlugins = jsonObject.value("android-extra-plugins"_L1);
if (!extraPlugins.isUndefined())
- options->extraPlugins = extraPlugins.toString().split(QLatin1Char(','));
+ options->extraPlugins = extraPlugins.toString().split(u',');
+ }
+
+ {
+ const QJsonValue systemLibsPath =
+ jsonObject.value("android-system-libs-prefix"_L1);
+ if (!systemLibsPath.isUndefined())
+ options->systemLibsPath = systemLibsPath.toString();
+ }
+
+ {
+ const QJsonValue noDeploy = jsonObject.value("android-no-deploy-qt-libs"_L1);
+ if (!noDeploy.isUndefined()) {
+ bool useUnbundled = parseCmakeBoolean(noDeploy);
+ options->deploymentMechanism = useUnbundled ? Options::Unbundled :
+ Options::Bundled;
+ }
}
{
- const QJsonValue stdcppPath = jsonObject.value(QLatin1String("stdcpp-path"));
+ const QJsonValue stdcppPath = jsonObject.value("stdcpp-path"_L1);
if (stdcppPath.isUndefined()) {
fprintf(stderr, "No stdcpp-path defined in json file.\n");
return false;
@@ -1097,7 +1169,7 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue qmlRootPath = jsonObject.value(QLatin1String("qml-root-path"));
+ const QJsonValue qmlRootPath = jsonObject.value("qml-root-path"_L1);
if (qmlRootPath.isString()) {
options->rootPaths.push_back(qmlRootPath.toString());
} else if (qmlRootPath.isArray()) {
@@ -1107,30 +1179,30 @@ bool readInputFile(Options *options)
options->rootPaths.push_back(path.toString());
}
} else {
- options->rootPaths.push_back(options->inputFileName);
+ options->rootPaths.push_back(QFileInfo(options->inputFileName).absolutePath());
}
}
{
- const QJsonValue qmlImportPaths = jsonObject.value(QLatin1String("qml-import-paths"));
+ const QJsonValue qmlImportPaths = jsonObject.value("qml-import-paths"_L1);
if (!qmlImportPaths.isUndefined())
- options->qmlImportPaths = qmlImportPaths.toString().split(QLatin1Char(','));
+ options->qmlImportPaths = qmlImportPaths.toString().split(u',');
}
{
- const QJsonValue qmlImportScannerBinaryPath = jsonObject.value(QLatin1String("qml-importscanner-binary"));
+ const QJsonValue qmlImportScannerBinaryPath = jsonObject.value("qml-importscanner-binary"_L1);
if (!qmlImportScannerBinaryPath.isUndefined())
options->qmlImportScannerBinaryPath = qmlImportScannerBinaryPath.toString();
}
{
- const QJsonValue rccBinaryPath = jsonObject.value(QLatin1String("rcc-binary"));
+ const QJsonValue rccBinaryPath = jsonObject.value("rcc-binary"_L1);
if (!rccBinaryPath.isUndefined())
options->rccBinaryPath = rccBinaryPath.toString();
}
{
- const QJsonValue applicationBinary = jsonObject.value(QLatin1String("application-binary"));
+ const QJsonValue applicationBinary = jsonObject.value("application-binary"_L1);
if (applicationBinary.isUndefined()) {
fprintf(stderr, "No application binary defined in json file.\n");
return false;
@@ -1140,7 +1212,7 @@ bool readInputFile(Options *options)
for (auto it = options->architectures.constBegin(); it != options->architectures.constEnd(); ++it) {
if (!it->enabled)
continue;
- auto appBinaryPath = QLatin1String("%1/libs/%2/lib%3_%2.so").arg(options->outputDirectory, it.key(), options->applicationBinary);
+ auto appBinaryPath = "%1/libs/%2/lib%3_%2.so"_L1.arg(options->outputDirectory, it.key(), options->applicationBinary);
if (!QFile::exists(appBinaryPath)) {
fprintf(stderr, "Cannot find application binary in build dir %s.\n", qPrintable(appBinaryPath));
return false;
@@ -1150,22 +1222,21 @@ bool readInputFile(Options *options)
}
{
- const QJsonValue deploymentDependencies = jsonObject.value(QLatin1String("deployment-dependencies"));
+ using ItFlag = QDirListing::IteratorFlag;
+ const QJsonValue deploymentDependencies = jsonObject.value("deployment-dependencies"_L1);
if (!deploymentDependencies.isUndefined()) {
QString deploymentDependenciesString = deploymentDependencies.toString();
- const auto dependencies = QStringView{deploymentDependenciesString}.split(QLatin1Char(','));
+ const auto dependencies = QStringView{deploymentDependenciesString}.split(u',');
for (const auto &dependency : dependencies) {
QString path = options->qtInstallDirectory + QChar::fromLatin1('/');
path += dependency;
if (QFileInfo(path).isDir()) {
- QDirIterator iterator(path, QDirIterator::Subdirectories);
- while (iterator.hasNext()) {
- iterator.next();
- if (iterator.fileInfo().isFile()) {
- QString subPath = iterator.filePath();
+ for (const auto &dirEntry : QDirListing(path, ItFlag::Recursive)) {
+ if (dirEntry.isFile()) {
+ const QString subPath = dirEntry.filePath();
auto arch = fileArchitecture(*options, subPath);
if (!arch.isEmpty()) {
- options->qtDependencies[arch].append(QtDependency(subPath.mid(options->qtInstallDirectory.length() + 1),
+ options->qtDependencies[arch].append(QtDependency(subPath.mid(options->qtInstallDirectory.size() + 1),
subPath));
} else if (options->verbose) {
fprintf(stderr, "Skipping \"%s\", unknown architecture\n", qPrintable(subPath));
@@ -1174,34 +1245,51 @@ bool readInputFile(Options *options)
}
}
} else {
- auto arch = fileArchitecture(*options, path);
- if (!arch.isEmpty()) {
- options->qtDependencies[arch].append(QtDependency(dependency.toString(), path));
- } else if (options->verbose) {
- fprintf(stderr, "Skipping \"%s\", unknown architecture\n", qPrintable(path));
- fflush(stderr);
+ auto qtDependency = [options](const QStringView &dependency,
+ const QString &arch) {
+ const auto installDir = options->architectures[arch].qtInstallDirectory;
+ const auto absolutePath = "%1/%2"_L1.arg(installDir, dependency.toString());
+ return QtDependency(dependency.toString(), absolutePath);
+ };
+
+ if (dependency.endsWith(QLatin1String(".so"))) {
+ auto arch = fileArchitecture(*options, path);
+ if (!arch.isEmpty()) {
+ options->qtDependencies[arch].append(qtDependency(dependency, arch));
+ } else if (options->verbose) {
+ fprintf(stderr, "Skipping \"%s\", unknown architecture\n", qPrintable(path));
+ fflush(stderr);
+ }
+ } else {
+ for (auto arch : options->architectures.keys())
+ options->qtDependencies[arch].append(qtDependency(dependency, arch));
}
}
}
}
}
{
- const QJsonValue qrcFiles = jsonObject.value(QLatin1String("qrcFiles"));
- options->qrcFiles = qrcFiles.toString().split(QLatin1Char(','), Qt::SkipEmptyParts);
+ const QJsonValue qrcFiles = jsonObject.value("qrcFiles"_L1);
+ options->qrcFiles = qrcFiles.toString().split(u',', Qt::SkipEmptyParts);
}
{
- const QJsonValue zstdCompressionFlag = jsonObject.value(QLatin1String("zstdCompression"));
+ const QJsonValue zstdCompressionFlag = jsonObject.value("zstdCompression"_L1);
if (zstdCompressionFlag.isBool()) {
options->isZstdCompressionEnabled = zstdCompressionFlag.toBool();
}
}
- options->packageName = packageNameFromAndroidManifest(options->androidSourceDirectory + QLatin1String("/AndroidManifest.xml"));
+ options->packageName = packageNameFromAndroidManifest(options->androidSourceDirectory + "/AndroidManifest.xml"_L1);
if (options->packageName.isEmpty())
- options->packageName = cleanPackageName(QLatin1String("org.qtproject.example.%1").arg(options->applicationBinary));
+ options->packageName = cleanPackageName("org.qtproject.example.%1"_L1.arg(options->applicationBinary));
return true;
}
+bool isDeployment(const Options *options, Options::DeploymentMechanism deployment)
+{
+ return options->deploymentMechanism == deployment;
+}
+
bool copyFiles(const QDir &sourceDirectory, const QDir &destinationDirectory, const Options &options, bool forceOverwrite = false)
{
const QFileInfoList entries = sourceDirectory.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
@@ -1213,7 +1301,7 @@ bool copyFiles(const QDir &sourceDirectory, const QDir &destinationDirectory, co
return false;
}
- if (!copyFiles(dir, QDir(destinationDirectory.path() + QLatin1Char('/') + dir.dirName()), options, forceOverwrite))
+ if (!copyFiles(dir, QDir(destinationDirectory.path() + u'/' + dir.dirName()), options, forceOverwrite))
return false;
} else {
QString destination = destinationDirectory.absoluteFilePath(entry.fileName());
@@ -1229,8 +1317,8 @@ void cleanTopFolders(const Options &options, const QDir &srcDir, const QString &
{
const auto dirs = srcDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs);
for (const QFileInfo &dir : dirs) {
- if (dir.fileName() != QLatin1String("libs"))
- deleteMissingFiles(options, dir.absoluteDir(), QDir(dstDir + dir.fileName()));
+ if (dir.fileName() != "libs"_L1)
+ deleteMissingFiles(options, dir.absoluteFilePath(), QDir(dstDir + dir.fileName()));
}
}
@@ -1239,13 +1327,15 @@ void cleanAndroidFiles(const Options &options)
if (!options.androidSourceDirectory.isEmpty())
cleanTopFolders(options, QDir(options.androidSourceDirectory), options.outputDirectory);
- cleanTopFolders(options, QDir(options.qtInstallDirectory + QLatin1String("/src/android/templates")),
+ cleanTopFolders(options,
+ QDir(options.qtInstallDirectory + u'/' +
+ options.qtDataDirectory + "/src/android/templates"_L1),
options.outputDirectory);
}
bool copyAndroidTemplate(const Options &options, const QString &androidTemplate, const QString &outDirPrefix = QString())
{
- QDir sourceDirectory(options.qtInstallDirectory + androidTemplate);
+ QDir sourceDirectory(options.qtInstallDirectory + u'/' + options.qtDataDirectory + androidTemplate);
if (!sourceDirectory.exists()) {
fprintf(stderr, "Cannot find template directory %s\n", qPrintable(sourceDirectory.absolutePath()));
return false;
@@ -1263,7 +1353,8 @@ bool copyAndroidTemplate(const Options &options, const QString &androidTemplate,
bool copyGradleTemplate(const Options &options)
{
- QDir sourceDirectory(options.qtInstallDirectory + QLatin1String("/src/3rdparty/gradle"));
+ QDir sourceDirectory(options.qtInstallDirectory + u'/' +
+ options.qtDataDirectory + "/src/3rdparty/gradle"_L1);
if (!sourceDirectory.exists()) {
fprintf(stderr, "Cannot find template directory %s\n", qPrintable(sourceDirectory.absolutePath()));
return false;
@@ -1286,7 +1377,7 @@ bool copyAndroidTemplate(const Options &options)
if (!copyGradleTemplate(options))
return false;
- if (!copyAndroidTemplate(options, QLatin1String("/src/android/templates")))
+ if (!copyAndroidTemplate(options, "/src/android/templates"_L1))
return false;
return true;
@@ -1314,8 +1405,16 @@ bool copyAndroidExtraLibs(Options *options)
if (options->extraLibs.isEmpty())
return true;
- if (options->verbose)
- fprintf(stdout, "Copying %zd external libraries to package.\n", size_t(options->extraLibs.size()));
+ if (options->verbose) {
+ switch (options->deploymentMechanism) {
+ case Options::Bundled:
+ fprintf(stdout, "Copying %zd external libraries to package.\n", size_t(options->extraLibs.size()));
+ break;
+ case Options::Unbundled:
+ fprintf(stdout, "Skip copying of external libraries.\n");
+ break;
+ };
+ }
for (const QString &extraLib : options->extraLibs) {
QFileInfo extraLibInfo(extraLib);
@@ -1328,19 +1427,21 @@ bool copyAndroidExtraLibs(Options *options)
fprintf(stdout, "Skipping \"%s\", architecture mismatch.\n", qPrintable(extraLib));
continue;
}
- if (!extraLibInfo.fileName().startsWith(QLatin1String("lib")) || extraLibInfo.suffix() != QLatin1String("so")) {
+ if (!extraLibInfo.fileName().startsWith("lib"_L1) || extraLibInfo.suffix() != "so"_L1) {
fprintf(stderr, "The file name of external library %s must begin with \"lib\" and end with the suffix \".so\".\n",
qPrintable(extraLib));
return false;
}
QString destinationFile(options->outputDirectory
- + QLatin1String("/libs/")
+ + "/libs/"_L1
+ options->currentArchitecture
- + QLatin1Char('/')
+ + u'/'
+ extraLibInfo.fileName());
- if (!copyFileIfNewer(extraLib, destinationFile, *options))
+ if (isDeployment(options, Options::Bundled)
+ && !copyFileIfNewer(extraLib, destinationFile, *options)) {
return false;
+ }
options->archExtraLibs[options->currentArchitecture] += extraLib;
}
@@ -1378,18 +1479,21 @@ bool copyAndroidExtraResources(Options *options)
}
QDir resourceDir(extraResource);
- QString assetsDir = options->outputDirectory + QLatin1String("/assets/") + resourceDir.dirName() + QLatin1Char('/');
- QString libsDir = options->outputDirectory + QLatin1String("/libs/") + options->currentArchitecture + QLatin1Char('/');
+ QString assetsDir = options->outputDirectory + "/assets/"_L1 +
+ resourceDir.dirName() + u'/';
+ QString libsDir = options->outputDirectory + "/libs/"_L1 + options->currentArchitecture + u'/';
const QStringList files = allFilesInside(resourceDir, resourceDir);
for (const QString &resourceFile : files) {
QString originFile(resourceDir.filePath(resourceFile));
QString destinationFile;
- if (!resourceFile.endsWith(QLatin1String(".so"))) {
+ if (!resourceFile.endsWith(".so"_L1)) {
destinationFile = assetsDir + resourceFile;
} else {
- if (!checkArchitecture(*options, originFile))
+ if (isDeployment(options, Options::Unbundled)
+ || !checkArchitecture(*options, originFile)) {
continue;
+ }
destinationFile = libsDir + resourceFile;
options->archExtraPlugins[options->currentArchitecture] += resourceFile;
}
@@ -1422,7 +1526,7 @@ bool updateFile(const QString &fileName, const QHash<QString, QString> &replacem
forever {
int index = contents.indexOf(it.key().toUtf8());
if (index >= 0) {
- contents.replace(index, it.key().length(), it.value().toUtf8());
+ contents.replace(index, it.key().size(), it.value().toUtf8());
hasReplacements = true;
} else {
break;
@@ -1450,7 +1554,7 @@ bool updateLibsXml(Options *options)
if (options->verbose)
fprintf(stdout, " -- res/values/libs.xml\n");
- QString fileName = options->outputDirectory + QLatin1String("/res/values/libs.xml");
+ QString fileName = options->outputDirectory + "/res/values/libs.xml"_L1;
if (!QFile::exists(fileName)) {
fprintf(stderr, "Cannot find %s in prepared packaged. This file is required.\n", qPrintable(fileName));
return false;
@@ -1463,23 +1567,38 @@ bool updateLibsXml(Options *options)
for (auto it = options->architectures.constBegin(); it != options->architectures.constEnd(); ++it) {
if (!it->enabled)
continue;
- QString libsPath = QLatin1String("libs/") + it.key() + QLatin1Char('/');
- qtLibs += QLatin1String(" <item>%1;%2</item>\n").arg(it.key(), options->stdCppName);
+ qtLibs += " <item>%1;%2</item>\n"_L1.arg(it.key(), options->stdCppName);
for (const Options::BundledFile &bundledFile : options->bundledFiles[it.key()]) {
- if (bundledFile.second.startsWith(QLatin1String("lib/"))) {
+ if (bundledFile.second.startsWith("lib/lib"_L1)) {
+ if (!bundledFile.second.endsWith(".so"_L1)) {
+ fprintf(stderr,
+ "The bundled library %s doesn't end with .so. Android only supports "
+ "versionless libraries ending with the .so suffix.\n",
+ qPrintable(bundledFile.second));
+ return false;
+ }
QString s = bundledFile.second.mid(sizeof("lib/lib") - 1);
s.chop(sizeof(".so") - 1);
- qtLibs += QLatin1String(" <item>%1;%2</item>\n").arg(it.key(), s);
+ qtLibs += " <item>%1;%2</item>\n"_L1.arg(it.key(), s);
}
}
if (!options->archExtraLibs[it.key()].isEmpty()) {
for (const QString &extraLib : options->archExtraLibs[it.key()]) {
QFileInfo extraLibInfo(extraLib);
- QString name = extraLibInfo.fileName().mid(sizeof("lib") - 1);
- name.chop(sizeof(".so") - 1);
- extraLibs += QLatin1String(" <item>%1;%2</item>\n").arg(it.key(), name);
+ if (extraLibInfo.fileName().startsWith("lib"_L1)) {
+ if (!extraLibInfo.fileName().endsWith(".so"_L1)) {
+ fprintf(stderr,
+ "The library %s doesn't end with .so. Android only supports "
+ "versionless libraries ending with the .so suffix.\n",
+ qPrintable(extraLibInfo.fileName()));
+ return false;
+ }
+ QString name = extraLibInfo.fileName().mid(sizeof("lib") - 1);
+ name.chop(sizeof(".so") - 1);
+ extraLibs += " <item>%1;%2</item>\n"_L1.arg(it.key(), name);
+ }
}
}
@@ -1489,25 +1608,21 @@ bool updateLibsXml(Options *options)
if (localLibs.isEmpty()) {
QString plugin;
for (const QtDependency &qtDependency : options->qtDependencies[it.key()]) {
- if (qtDependency.relativePath.endsWith(QLatin1String("libqtforandroid.so"))
- || qtDependency.relativePath.endsWith(QLatin1String("libqtforandroidGL.so"))) {
- if (!plugin.isEmpty() && plugin != qtDependency.relativePath) {
- fprintf(stderr, "Both platform plugins libqtforandroid.so and libqtforandroidGL.so included in package. Please include only one.\n");
- return false;
- }
-
+ if (qtDependency.relativePath.contains("libplugins_platforms_qtforandroid_"_L1))
plugin = qtDependency.relativePath;
- }
- if (qtDependency.relativePath.contains(QLatin1String("libQt5OpenGL"))
- || qtDependency.relativePath.contains(QLatin1String("libQt5Quick"))) {
+
+ if (qtDependency.relativePath.contains(
+ QString::asprintf("libQt%dOpenGL", QT_VERSION_MAJOR))
+ || qtDependency.relativePath.contains(
+ QString::asprintf("libQt%dQuick", QT_VERSION_MAJOR))) {
options->usesOpenGL |= true;
- break;
}
}
if (plugin.isEmpty()) {
fflush(stdout);
- fprintf(stderr, "No platform plugin, neither libqtforandroid.so or libqtforandroidGL.so, included in package. Please include one.\n");
+ fprintf(stderr, "No platform plugin (libplugins_platforms_qtforandroid.so) included"
+ " in the deployment. Make sure the app links to Qt Gui library.\n");
fflush(stderr);
return false;
}
@@ -1519,10 +1634,10 @@ bool updateLibsXml(Options *options)
// remove all paths
for (auto &lib : localLibs) {
- if (lib.endsWith(QLatin1String(".so")))
- lib = lib.mid(lib.lastIndexOf(QLatin1Char('/')) + 1);
+ if (lib.endsWith(".so"_L1))
+ lib = lib.mid(lib.lastIndexOf(u'/') + 1);
}
- allLocalLibs += QLatin1String(" <item>%1;%2</item>\n").arg(it.key(), localLibs.join(QLatin1Char(':')));
+ allLocalLibs += " <item>%1;%2</item>\n"_L1.arg(it.key(), localLibs.join(u':'));
}
options->initClasses.removeDuplicates();
@@ -1531,14 +1646,15 @@ bool updateLibsXml(Options *options)
replacements[QStringLiteral("<!-- %%INSERT_QT_LIBS%% -->")] += qtLibs.trimmed();
replacements[QStringLiteral("<!-- %%INSERT_LOCAL_LIBS%% -->")] = allLocalLibs.trimmed();
replacements[QStringLiteral("<!-- %%INSERT_EXTRA_LIBS%% -->")] = extraLibs.trimmed();
- const QString initClasses = options->initClasses.join(QLatin1Char(':'));
+ const QString initClasses = options->initClasses.join(u':');
replacements[QStringLiteral("<!-- %%INSERT_INIT_CLASSES%% -->")] = initClasses;
- // Bundle and use libs from the apk because currently we don't have a way avoid
- // duplicating them.
- replacements[QStringLiteral("<!-- %%BUNDLE_LOCAL_QT_LIBS%% -->")] = QLatin1String("1");
- replacements[QStringLiteral("<!-- %%USE_LOCAL_QT_LIBS%% -->")] = QLatin1String("1");
-
+ // Set BUNDLE_LOCAL_QT_LIBS based on the deployment used
+ replacements[QStringLiteral("<!-- %%BUNDLE_LOCAL_QT_LIBS%% -->")]
+ = isDeployment(options, Options::Unbundled) ? "0"_L1 : "1"_L1;
+ replacements[QStringLiteral("<!-- %%USE_LOCAL_QT_LIBS%% -->")] = "1"_L1;
+ replacements[QStringLiteral("<!-- %%SYSTEM_LIBS_PREFIX%% -->")] =
+ isDeployment(options, Options::Unbundled) ? options->systemLibsPath : QStringLiteral("");
if (!updateFile(fileName, replacements))
return false;
@@ -1554,7 +1670,7 @@ bool updateStringsXml(const Options &options)
QHash<QString, QString> replacements;
replacements[QStringLiteral("<!-- %%INSERT_APP_NAME%% -->")] = options.applicationBinary;
- QString fileName = options.outputDirectory + QLatin1String("/res/values/strings.xml");
+ QString fileName = options.outputDirectory + "/res/values/strings.xml"_L1;
if (!QFile::exists(fileName)) {
if (options.verbose)
fprintf(stdout, " -- Create strings.xml since it's missing.\n");
@@ -1586,22 +1702,22 @@ bool updateAndroidManifest(Options &options)
replacements[QStringLiteral("-- %%INSERT_APP_LIB_NAME%% --")] = options.applicationBinary;
replacements[QStringLiteral("-- %%INSERT_VERSION_NAME%% --")] = options.versionName;
replacements[QStringLiteral("-- %%INSERT_VERSION_CODE%% --")] = options.versionCode;
- replacements[QStringLiteral("package=\"org.qtproject.example\"")] = QLatin1String("package=\"%1\"").arg(options.packageName);
+ replacements[QStringLiteral("package=\"org.qtproject.example\"")] = "package=\"%1\""_L1.arg(options.packageName);
QString permissions;
- for (const QString &permission : qAsConst(options.permissions))
- permissions += QLatin1String(" <uses-permission android:name=\"%1\" />\n").arg(permission);
+ for (const QString &permission : std::as_const(options.permissions))
+ permissions += " <uses-permission android:name=\"%1\" />\n"_L1.arg(permission);
replacements[QStringLiteral("<!-- %%INSERT_PERMISSIONS -->")] = permissions.trimmed();
QString features;
- for (const QString &feature : qAsConst(options.features))
- features += QLatin1String(" <uses-feature android:name=\"%1\" android:required=\"false\" />\n").arg(feature);
+ for (const QString &feature : std::as_const(options.features))
+ features += " <uses-feature android:name=\"%1\" android:required=\"false\" />\n"_L1.arg(feature);
if (options.usesOpenGL)
- features += QLatin1String(" <uses-feature android:glEsVersion=\"0x00020000\" android:required=\"true\" />");
+ features += " <uses-feature android:glEsVersion=\"0x00020000\" android:required=\"true\" />"_L1;
replacements[QStringLiteral("<!-- %%INSERT_FEATURES -->")] = features.trimmed();
- QString androidManifestPath = options.outputDirectory + QLatin1String("/AndroidManifest.xml");
+ QString androidManifestPath = options.outputDirectory + "/AndroidManifest.xml"_L1;
if (!updateFile(androidManifestPath, replacements))
return false;
@@ -1619,28 +1735,27 @@ bool updateAndroidManifest(Options &options)
reader.readNext();
if (reader.isStartElement()) {
- if (reader.name() == QLatin1String("manifest")) {
- if (!reader.attributes().hasAttribute(QLatin1String("package"))) {
+ if (reader.name() == "manifest"_L1) {
+ if (!reader.attributes().hasAttribute("package"_L1)) {
fprintf(stderr, "Invalid android manifest file: %s\n", qPrintable(androidManifestPath));
return false;
}
- options.packageName = reader.attributes().value(QLatin1String("package")).toString();
- } else if (reader.name() == QLatin1String("uses-sdk")) {
- if (reader.attributes().hasAttribute(QLatin1String("android:minSdkVersion")))
- if (reader.attributes().value(QLatin1String("android:minSdkVersion")).toInt() < 23) {
+ options.packageName = reader.attributes().value("package"_L1).toString();
+ } else if (reader.name() == "uses-sdk"_L1) {
+ if (reader.attributes().hasAttribute("android:minSdkVersion"_L1))
+ if (reader.attributes().value("android:minSdkVersion"_L1).toInt() < 23) {
fprintf(stderr, "Invalid minSdkVersion version, minSdkVersion must be >= 23\n");
return false;
}
- } else if ((reader.name() == QLatin1String("application") ||
- reader.name() == QLatin1String("activity")) &&
- reader.attributes().hasAttribute(QLatin1String("android:label")) &&
- reader.attributes().value(QLatin1String("android:label")) == QLatin1String("@string/app_name")) {
+ } else if ((reader.name() == "application"_L1 ||
+ reader.name() == "activity"_L1) &&
+ reader.attributes().hasAttribute("android:label"_L1) &&
+ reader.attributes().value("android:label"_L1) == "@string/app_name"_L1) {
checkOldAndroidLabelString = true;
- } else if (reader.name() == QLatin1String("meta-data")) {
- const auto name = reader.attributes().value(QLatin1String("android:name"));
- const auto value = reader.attributes().value(QLatin1String("android:value"));
- if (name == QLatin1String("android.app.lib_name")
- && value.contains(QLatin1Char(' '))) {
+ } else if (reader.name() == "meta-data"_L1) {
+ const auto name = reader.attributes().value("android:name"_L1);
+ const auto value = reader.attributes().value("android:value"_L1);
+ if (name == "android.app.lib_name"_L1 && value.contains(u' ')) {
fprintf(stderr, "The Activity's android.app.lib_name should not contain"
" spaces.\n");
return false;
@@ -1683,20 +1798,40 @@ static QString absoluteFilePath(const Options *options, const QString &relativeF
// Use extraLibraryDirs as the extra library lookup folder if it is expected to find a file in
// any $prefix/lib folder.
// Library directories from a build tree(extraLibraryDirs) have the higher priority.
- if (relativeFileName.startsWith(QLatin1String("lib/"))) {
+ if (relativeFileName.startsWith("lib/"_L1)) {
for (const auto &dir : options->extraLibraryDirs) {
- const QString path = dir + QLatin1Char('/') + relativeFileName.mid(sizeof("lib/") - 1);
+ const QString path = dir + u'/' + relativeFileName.mid(sizeof("lib/") - 1);
if (QFile::exists(path))
return path;
}
}
for (const auto &prefix : options->extraPrefixDirs) {
- const QString path = prefix + QLatin1Char('/') + relativeFileName;
+ const QString path = prefix + u'/' + relativeFileName;
if (QFile::exists(path))
return path;
}
- return options->qtInstallDirectory + QLatin1Char('/') + relativeFileName;
+
+ if (relativeFileName.endsWith("-android-dependencies.xml"_L1)) {
+ for (const auto &dir : options->extraLibraryDirs) {
+ const QString path = dir + u'/' + relativeFileName;
+ if (QFile::exists(path))
+ return path;
+ }
+ return options->qtInstallDirectory + u'/' + options->qtLibsDirectory +
+ u'/' + relativeFileName;
+ }
+
+ if (relativeFileName.startsWith("jar/"_L1)) {
+ return options->qtInstallDirectory + u'/' + options->qtDataDirectory +
+ u'/' + relativeFileName;
+ }
+
+ if (relativeFileName.startsWith("lib/"_L1)) {
+ return options->qtInstallDirectory + u'/' + options->qtLibsDirectory +
+ u'/' + relativeFileName.mid(sizeof("lib/") - 1);
+ }
+ return options->qtInstallDirectory + u'/' + relativeFileName;
}
QList<QtDependency> findFilesRecursively(const Options &options, const QFileInfo &info, const QString &rootPath)
@@ -1718,19 +1853,63 @@ QList<QtDependency> findFilesRecursively(const Options &options, const QFileInfo
return ret;
} else {
- return QList<QtDependency>() << QtDependency(info.absoluteFilePath().mid(rootPath.length()), info.absoluteFilePath());
+ return QList<QtDependency>() << QtDependency(info.absoluteFilePath().mid(rootPath.size()), info.absoluteFilePath());
}
}
QList<QtDependency> findFilesRecursively(const Options &options, const QString &fileName)
{
+ // We try to find the fileName in extraPrefixDirs first. The function behaves differently
+ // depending on what the fileName points to. If fileName is a file then we try to find the
+ // first occurrence in extraPrefixDirs and return this file. If fileName is directory function
+ // iterates over it and looks for deployment artifacts in each 'extraPrefixDirs' entry.
+ // Also we assume that if the fileName is recognized as a directory once it will be directory
+ // for every 'extraPrefixDirs' entry.
+ QList<QtDependency> deps;
for (const auto &prefix : options.extraPrefixDirs) {
- QFileInfo info(prefix + QLatin1Char('/') + fileName);
- if (info.exists())
- return findFilesRecursively(options, info, prefix + QLatin1Char('/'));
+ QFileInfo info(prefix + u'/' + fileName);
+ if (info.exists()) {
+ if (info.isDir())
+ deps.append(findFilesRecursively(options, info, prefix + u'/'));
+ else
+ return findFilesRecursively(options, info, prefix + u'/');
+ }
+ }
+
+ // Usually android deployment settings contain Qt install directory in extraPrefixDirs.
+ if (std::find(options.extraPrefixDirs.begin(), options.extraPrefixDirs.end(),
+ options.qtInstallDirectory) == options.extraPrefixDirs.end()) {
+ QFileInfo info(options.qtInstallDirectory + "/"_L1 + fileName);
+ QFileInfo rootPath(options.qtInstallDirectory + "/"_L1);
+ deps.append(findFilesRecursively(options, info, rootPath.absolutePath()));
+ }
+ return deps;
+}
+
+void readDependenciesFromFiles(Options *options, const QList<QtDependency> &files,
+ QSet<QString> &usedDependencies,
+ QSet<QString> &remainingDependencies)
+{
+ for (const QtDependency &fileName : files) {
+ if (usedDependencies.contains(fileName.absolutePath))
+ continue;
+
+ if (fileName.absolutePath.endsWith(".so"_L1)) {
+ if (!readDependenciesFromElf(options, fileName.absolutePath, &usedDependencies,
+ &remainingDependencies)) {
+ fprintf(stdout, "Skipping file dependency: %s\n",
+ qPrintable(fileName.relativePath));
+ continue;
+ }
+ }
+ usedDependencies.insert(fileName.absolutePath);
+
+ if (options->verbose) {
+ fprintf(stdout, "Appending file dependency: %s\n", qPrintable(fileName.relativePath));
+ }
+
+ options->qtDependencies[options->currentArchitecture].append(fileName);
}
- QFileInfo info(options.qtInstallDirectory + QLatin1Char('/') + fileName);
- return findFilesRecursively(options, info, options.qtInstallDirectory + QLatin1Char('/'));
}
bool readAndroidDependencyXml(Options *options,
@@ -1738,7 +1917,7 @@ bool readAndroidDependencyXml(Options *options,
QSet<QString> *usedDependencies,
QSet<QString> *remainingDependencies)
{
- QString androidDependencyName = absoluteFilePath(options, QLatin1String("/lib/%1-android-dependencies.xml").arg(moduleName));
+ QString androidDependencyName = absoluteFilePath(options, "%1-android-dependencies.xml"_L1.arg(moduleName));
QFile androidDependencyFile(androidDependencyName);
if (androidDependencyFile.exists()) {
@@ -1755,35 +1934,27 @@ bool readAndroidDependencyXml(Options *options,
reader.readNext();
if (reader.isStartElement()) {
- if (reader.name() == QLatin1String("bundled")) {
- if (!reader.attributes().hasAttribute(QLatin1String("file"))) {
+ if (reader.name() == "bundled"_L1) {
+ if (!reader.attributes().hasAttribute("file"_L1)) {
fprintf(stderr, "Invalid android dependency file: %s\n", qPrintable(androidDependencyName));
return false;
}
- QString file = reader.attributes().value(QLatin1String("file")).toString();
+ QString file = reader.attributes().value("file"_L1).toString();
- // Special case, since this is handled by qmlimportscanner instead
- if (!options->rootPaths.empty()
- && (file == QLatin1String("qml") || file == QLatin1String("qml/")))
+ if (reader.attributes().hasAttribute("type"_L1)
+ && reader.attributes().value("type"_L1) == "plugin_dir"_L1
+ && !options->androidDeployPlugins.isEmpty()) {
continue;
+ }
const QList<QtDependency> fileNames = findFilesRecursively(*options, file);
- for (const QtDependency &fileName : fileNames) {
- if (usedDependencies->contains(fileName.absolutePath))
- continue;
-
- usedDependencies->insert(fileName.absolutePath);
-
- if (options->verbose)
- fprintf(stdout, "Appending dependency from xml: %s\n", qPrintable(fileName.relativePath));
-
- options->qtDependencies[options->currentArchitecture].append(fileName);
- }
- } else if (reader.name() == QLatin1String("jar")) {
- int bundling = reader.attributes().value(QLatin1String("bundling")).toInt();
- QString fileName = QDir::cleanPath(reader.attributes().value(QLatin1String("file")).toString());
- if (bundling == (options->deploymentMechanism == Options::Bundled)) {
+ readDependenciesFromFiles(options, fileNames, *usedDependencies,
+ *remainingDependencies);
+ } else if (reader.name() == "jar"_L1) {
+ int bundling = reader.attributes().value("bundling"_L1).toInt();
+ QString fileName = QDir::cleanPath(reader.attributes().value("file"_L1).toString());
+ if (bundling) {
QtDependency dependency(fileName, absoluteFilePath(options, fileName));
if (!usedDependencies->contains(dependency.absolutePath)) {
options->qtDependencies[options->currentArchitecture].append(dependency);
@@ -1791,13 +1962,13 @@ bool readAndroidDependencyXml(Options *options,
}
}
- if (reader.attributes().hasAttribute(QLatin1String("initClass"))) {
- options->initClasses.append(reader.attributes().value(QLatin1String("initClass")).toString());
+ if (reader.attributes().hasAttribute("initClass"_L1)) {
+ options->initClasses.append(reader.attributes().value("initClass"_L1).toString());
}
- } else if (reader.name() == QLatin1String("lib")) {
- QString fileName = QDir::cleanPath(reader.attributes().value(QLatin1String("file")).toString());
- if (reader.attributes().hasAttribute(QLatin1String("replaces"))) {
- QString replaces = reader.attributes().value(QLatin1String("replaces")).toString();
+ } else if (reader.name() == "lib"_L1) {
+ QString fileName = QDir::cleanPath(reader.attributes().value("file"_L1).toString());
+ if (reader.attributes().hasAttribute("replaces"_L1)) {
+ QString replaces = reader.attributes().value("replaces"_L1).toString();
for (int i=0; i<options->localLibs.size(); ++i) {
if (options->localLibs[options->currentArchitecture].at(i) == replaces) {
options->localLibs[options->currentArchitecture][i] = fileName;
@@ -1807,14 +1978,14 @@ bool readAndroidDependencyXml(Options *options,
} else if (!fileName.isEmpty()) {
options->localLibs[options->currentArchitecture].append(fileName);
}
- if (fileName.endsWith(QLatin1String(".so")) && checkArchitecture(*options, fileName)) {
+ if (fileName.endsWith(".so"_L1) && checkArchitecture(*options, fileName)) {
remainingDependencies->insert(fileName);
}
- } else if (reader.name() == QLatin1String("permission")) {
- QString name = reader.attributes().value(QLatin1String("name")).toString();
+ } else if (reader.name() == "permission"_L1) {
+ QString name = reader.attributes().value("name"_L1).toString();
options->permissions.append(name);
- } else if (reader.name() == QLatin1String("feature")) {
- QString name = reader.attributes().value(QLatin1String("name")).toString();
+ } else if (reader.name() == "feature"_L1) {
+ QString name = reader.attributes().value("name"_L1).toString();
options->features.append(name);
}
}
@@ -1835,19 +2006,13 @@ bool readAndroidDependencyXml(Options *options,
QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
{
- QString readElf = QLatin1String("%1/toolchains/%2/prebuilt/%3/bin/llvm-readobj").arg(options.ndkPath,
- options.toolchainPrefix,
- options.ndkHost);
-#if defined(Q_OS_WIN32)
- readElf += QLatin1String(".exe");
-#endif
-
+ QString readElf = llvmReadobjPath(options);
if (!QFile::exists(readElf)) {
fprintf(stderr, "Command does not exist: %s\n", qPrintable(readElf));
return QStringList();
}
- readElf = QLatin1String("%1 -needed-libs %2").arg(shellQuote(readElf), shellQuote(fileName));
+ readElf = "%1 --needed-libs %2"_L1.arg(shellQuote(readElf), shellQuote(fileName));
FILE *readElfCommand = openProcess(readElf);
if (!readElfCommand) {
@@ -1869,6 +2034,7 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
if (it == elfArchitectures.constEnd() || *it != options.currentArchitecture.toLatin1()) {
if (options.verbose)
fprintf(stdout, "Skipping \"%s\", architecture mismatch\n", qPrintable(fileName));
+ pclose(readElfCommand);
return {};
}
}
@@ -1878,7 +2044,7 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
if (!line.startsWith("lib"))
continue;
library = QString::fromLatin1(line);
- QString libraryName = QLatin1String("lib/") + library;
+ QString libraryName = "lib/"_L1 + library;
if (QFile::exists(absoluteFilePath(&options, libraryName)))
ret += libraryName;
}
@@ -1922,7 +2088,7 @@ bool readDependenciesFromElf(Options *options,
dependenciesToCheck.append(dependency);
}
- for (const QString &dependency : qAsConst(dependenciesToCheck)) {
+ for (const QString &dependency : std::as_const(dependenciesToCheck)) {
QString qtBaseName = dependency.mid(sizeof("lib/lib") - 1);
qtBaseName = qtBaseName.left(qtBaseName.size() - (sizeof(".so") - 1));
if (!readAndroidDependencyXml(options, qtBaseName, usedDependencies, remainingDependencies)) {
@@ -1933,41 +2099,38 @@ bool readDependenciesFromElf(Options *options,
return true;
}
-QString defaultLibexecDir()
-{
-#ifdef Q_OS_WIN32
- return QStringLiteral("bin");
-#else
- return QStringLiteral("libexec");
-#endif
-}
-
-bool goodToCopy(const Options *options, const QString &file, QStringList *unmetDependencies);
-bool checkQmlFileInRootPaths(const Options *options, const QString &absolutePath);
-
bool scanImports(Options *options, QSet<QString> *usedDependencies)
{
if (options->verbose)
fprintf(stdout, "Scanning for QML imports.\n");
QString qmlImportScanner;
- if (!options->qmlImportScannerBinaryPath.isEmpty())
+ if (!options->qmlImportScannerBinaryPath.isEmpty()) {
qmlImportScanner = options->qmlImportScannerBinaryPath;
- else
- qmlImportScanner = options->qtInstallDirectory + QLatin1String("/bin/qmlimportscanner");
-#if defined(Q_OS_WIN32)
- qmlImportScanner += QLatin1String(".exe");
-#endif
+ } else {
+ qmlImportScanner = execSuffixAppended(options->qtLibExecsDirectory +
+ "/qmlimportscanner"_L1);
+ }
QStringList importPaths;
- importPaths += shellQuote(options->qtInstallDirectory + QLatin1String("/qml"));
+ // In Conan's case, qtInstallDirectory will point only to qtbase installed files, which
+ // lacks a qml directory. We don't want to pass it as an import path if it doesn't exist
+ // because it will cause qmlimportscanner to fail.
+ // This also covers the case when only qtbase is installed in a regular Qt build.
+ const QString mainImportPath = options->qtInstallDirectory + u'/' + options->qtQmlDirectory;
+ if (QFile::exists(mainImportPath))
+ importPaths += shellQuote(mainImportPath);
+
+ // These are usually provided by CMake in the deployment json file from paths specified
+ // in CMAKE_FIND_ROOT_PATH. They might not have qml modules.
for (const QString &prefix : options->extraPrefixDirs)
- if (QDir().exists(prefix + QLatin1String("/qml")))
- importPaths += shellQuote(prefix + QLatin1String("/qml"));
+ if (QFile::exists(prefix + "/qml"_L1))
+ importPaths += shellQuote(prefix + "/qml"_L1);
- for (const QString &qmlImportPath : qAsConst(options->qmlImportPaths)) {
- if (QDir().exists(qmlImportPath)) {
+ // These are provided by both CMake and qmake.
+ for (const QString &qmlImportPath : std::as_const(options->qmlImportPaths)) {
+ if (QFile::exists(qmlImportPath)) {
importPaths += shellQuote(qmlImportPath);
} else {
fprintf(stderr, "Warning: QML import path %s does not exist.\n",
@@ -1994,7 +2157,7 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
if (!QFile::exists(qmlImportScanner)) {
fprintf(stderr, "%s: qmlimportscanner not found at %s\n",
- qmlImportExists ? QLatin1String("Error").data() : QLatin1String("Warning").data(),
+ qmlImportExists ? "Error"_L1.data() : "Warning"_L1.data(),
qPrintable(qmlImportScanner));
return true;
}
@@ -2002,23 +2165,23 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
for (auto rootPath : options->rootPaths) {
rootPath = QFileInfo(rootPath).absoluteFilePath();
- if (!rootPath.endsWith(QLatin1Char('/')))
- rootPath += QLatin1Char('/');
+ if (!rootPath.endsWith(u'/'))
+ rootPath += u'/';
// After checking for qml folder imports we can add rootPath
if (!rootPath.isEmpty())
importPaths += shellQuote(rootPath);
- qmlImportScanner += QLatin1String(" -rootPath %1").arg(shellQuote(rootPath));
+ qmlImportScanner += " -rootPath %1"_L1.arg(shellQuote(rootPath));
}
if (!options->qrcFiles.isEmpty()) {
- qmlImportScanner += QLatin1String(" -qrcFiles");
+ qmlImportScanner += " -qrcFiles"_L1;
for (const QString &qrcFile : options->qrcFiles)
- qmlImportScanner += QLatin1Char(' ') + shellQuote(qrcFile);
+ qmlImportScanner += u' ' + shellQuote(qrcFile);
}
- qmlImportScanner += QLatin1String(" -importPath %1").arg(importPaths.join(QLatin1Char(' ')));
+ qmlImportScanner += " -importPath %1"_L1.arg(importPaths.join(u' '));
if (options->verbose) {
fprintf(stdout, "Running qmlimportscanner with the following command: %s\n",
@@ -2039,6 +2202,7 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
QJsonDocument jsonDocument = QJsonDocument::fromJson(output);
if (jsonDocument.isNull()) {
fprintf(stderr, "Invalid json output from qmlimportscanner.\n");
+ pclose(qmlImportScannerCommand);
return false;
}
@@ -2047,14 +2211,15 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
QJsonValue value = jsonArray.at(i);
if (!value.isObject()) {
fprintf(stderr, "Invalid format of qmlimportscanner output.\n");
+ pclose(qmlImportScannerCommand);
return false;
}
QJsonObject object = value.toObject();
- QString path = object.value(QLatin1String("path")).toString();
+ QString path = object.value("path"_L1).toString();
if (path.isEmpty()) {
fprintf(stderr, "Warning: QML import could not be resolved in any of the import paths: %s\n",
- qPrintable(object.value(QLatin1String("name")).toString()));
+ qPrintable(object.value("name"_L1).toString()));
} else {
if (options->verbose)
fprintf(stdout, " -- Adding '%s' as QML dependency\n", qPrintable(path));
@@ -2069,24 +2234,22 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
}
QString absolutePath = info.absolutePath();
- if (!absolutePath.endsWith(QLatin1Char('/')))
- absolutePath += QLatin1Char('/');
+ if (!absolutePath.endsWith(u'/'))
+ absolutePath += u'/';
- if (checkQmlFileInRootPaths(options, absolutePath)) {
+ const QUrl url(object.value("name"_L1).toString());
+
+ const QString moduleUrlPath = u"/"_s + url.toString().replace(u'.', u'/');
+ if (checkCanImportFromRootPaths(options, info.absolutePath(), moduleUrlPath)) {
if (options->verbose)
fprintf(stdout, " -- Skipping because path is in QML root path.\n");
continue;
}
QString importPathOfThisImport;
- for (const QString &importPath : qAsConst(importPaths)) {
-#if defined(Q_OS_WIN32)
- Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
-#else
- Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
-#endif
+ for (const QString &importPath : std::as_const(importPaths)) {
QString cleanImportPath = QDir::cleanPath(importPath);
- if (info.absoluteFilePath().startsWith(cleanImportPath, caseSensitivity)) {
+ if (QFile::exists(cleanImportPath + moduleUrlPath)) {
importPathOfThisImport = importPath;
break;
}
@@ -2094,26 +2257,27 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
if (importPathOfThisImport.isEmpty()) {
fprintf(stderr, "Import found outside of import paths: %s.\n", qPrintable(info.absoluteFilePath()));
+ pclose(qmlImportScannerCommand);
return false;
}
- importPathOfThisImport = QDir(importPathOfThisImport).absolutePath() + QLatin1Char('/');
+ importPathOfThisImport = QDir(importPathOfThisImport).absolutePath() + u'/';
QList<QtDependency> qmlImportsDependencies;
auto collectQmlDependency = [&usedDependencies, &qmlImportsDependencies,
&importPathOfThisImport](const QString &filePath) {
if (!usedDependencies->contains(filePath)) {
usedDependencies->insert(filePath);
qmlImportsDependencies += QtDependency(
- QLatin1String("qml/") + filePath.mid(importPathOfThisImport.size()),
+ "qml/"_L1 + filePath.mid(importPathOfThisImport.size()),
filePath);
}
};
- QString plugin = object.value(QLatin1String("plugin")).toString();
- bool pluginIsOptional = object.value(QLatin1String("pluginIsOptional")).toBool();
+ QString plugin = object.value("plugin"_L1).toString();
+ bool pluginIsOptional = object.value("pluginIsOptional"_L1).toBool();
QFileInfo pluginFileInfo = QFileInfo(
- path + QLatin1Char('/') + QLatin1String("lib") + plugin + QLatin1Char('_')
- + options->currentArchitecture + QLatin1String(".so"));
+ path + u'/' + "lib"_L1 + plugin + u'_'
+ + options->currentArchitecture + ".so"_L1);
QString pluginFilePath = pluginFileInfo.absoluteFilePath();
QSet<QString> remainingDependencies;
if (pluginFileInfo.exists() && checkArchitecture(*options, pluginFilePath)
@@ -2126,19 +2290,19 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
continue;
}
- QFileInfo qmldirFileInfo = QFileInfo(path + QLatin1Char('/') + QLatin1String("qmldir"));
+ QFileInfo qmldirFileInfo = QFileInfo(path + u'/' + "qmldir"_L1);
if (qmldirFileInfo.exists()) {
collectQmlDependency(qmldirFileInfo.absoluteFilePath());
}
- QString prefer = object.value(QLatin1String("prefer")).toString();
+ QString prefer = object.value("prefer"_L1).toString();
// If the preferred location of Qml files points to the Qt resources, this means
// that all Qml files has been embedded into plugin and we should not copy them to the
// android rcc bundle
- if (!prefer.startsWith(QLatin1String(":/"))) {
+ if (!prefer.startsWith(":/"_L1)) {
QVariantList qmlFiles =
- object.value(QLatin1String("components")).toArray().toVariantList();
- qmlFiles.append(object.value(QLatin1String("scripts")).toArray().toVariantList());
+ object.value("components"_L1).toArray().toVariantList();
+ qmlFiles.append(object.value("scripts"_L1).toArray().toVariantList());
bool qmlFilesMissing = false;
for (const auto &qmlFileEntry : qmlFiles) {
QFileInfo fileInfo(qmlFileEntry.toString());
@@ -2161,13 +2325,15 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
}
}
+ pclose(qmlImportScannerCommand);
return true;
}
-bool checkQmlFileInRootPaths(const Options *options, const QString &absolutePath)
+bool checkCanImportFromRootPaths(const Options *options, const QString &absolutePath,
+ const QString &moduleUrlPath)
{
for (auto rootPath : options->rootPaths) {
- if (absolutePath.startsWith(rootPath))
+ if ((rootPath + moduleUrlPath) == absolutePath)
return true;
}
return false;
@@ -2196,8 +2362,8 @@ bool runCommand(const Options &options, const QString &command)
bool createRcc(const Options &options)
{
- auto assetsDir = QLatin1String("%1/assets").arg(options.outputDirectory);
- if (!QDir{QLatin1String("%1/android_rcc_bundle").arg(assetsDir)}.exists()) {
+ auto assetsDir = "%1/assets"_L1.arg(options.outputDirectory);
+ if (!QDir{"%1/android_rcc_bundle"_L1.arg(assetsDir)}.exists()) {
fprintf(stdout, "Skipping createRCC\n");
return true;
}
@@ -2210,44 +2376,39 @@ bool createRcc(const Options &options)
if (!options.rccBinaryPath.isEmpty()) {
rcc = options.rccBinaryPath;
} else {
- rcc = options.qtInstallDirectory + QLatin1Char('/') + defaultLibexecDir()
- + QLatin1String("/rcc");
+ rcc = execSuffixAppended(options.qtLibExecsDirectory + "/rcc"_L1);
}
-#if defined(Q_OS_WIN32)
- rcc += QLatin1String(".exe");
-#endif
-
if (!QFile::exists(rcc)) {
fprintf(stderr, "rcc not found: %s\n", qPrintable(rcc));
return false;
}
auto currentDir = QDir::currentPath();
- if (!QDir::setCurrent(QLatin1String("%1/android_rcc_bundle").arg(assetsDir))) {
- fprintf(stderr, "Cannot set current dir to: %s\n", qPrintable(QLatin1String("%1/android_rcc_bundle").arg(assetsDir)));
+ if (!QDir::setCurrent("%1/android_rcc_bundle"_L1.arg(assetsDir))) {
+ fprintf(stderr, "Cannot set current dir to: %s\n", qPrintable("%1/android_rcc_bundle"_L1.arg(assetsDir)));
return false;
}
- bool res = runCommand(options, QLatin1String("%1 --project -o %2").arg(rcc, shellQuote(QLatin1String("%1/android_rcc_bundle.qrc").arg(assetsDir))));
+ bool res = runCommand(options, "%1 --project -o %2"_L1.arg(rcc, shellQuote("%1/android_rcc_bundle.qrc"_L1.arg(assetsDir))));
if (!res)
return false;
- QLatin1String noZstd;
+ QLatin1StringView noZstd;
if (!options.isZstdCompressionEnabled)
- noZstd = QLatin1String("--no-zstd");
+ noZstd = "--no-zstd"_L1;
- QFile::rename(QLatin1String("%1/android_rcc_bundle.qrc").arg(assetsDir), QLatin1String("%1/android_rcc_bundle/android_rcc_bundle.qrc").arg(assetsDir));
+ QFile::rename("%1/android_rcc_bundle.qrc"_L1.arg(assetsDir), "%1/android_rcc_bundle/android_rcc_bundle.qrc"_L1.arg(assetsDir));
- res = runCommand(options, QLatin1String("%1 %2 %3 --binary -o %4 android_rcc_bundle.qrc").arg(rcc, shellQuote(QLatin1String("--root=/android_rcc_bundle/")),
- noZstd,
- shellQuote(QLatin1String("%1/android_rcc_bundle.rcc").arg(assetsDir))));
+ res = runCommand(options, "%1 %2 %3 --binary -o %4 android_rcc_bundle.qrc"_L1.arg(rcc, shellQuote("--root=/android_rcc_bundle/"_L1),
+ noZstd,
+ shellQuote("%1/android_rcc_bundle.rcc"_L1.arg(assetsDir))));
if (!QDir::setCurrent(currentDir)) {
fprintf(stderr, "Cannot set current dir to: %s\n", qPrintable(currentDir));
return false;
}
if (!options.noRccBundleCleanup) {
- QFile::remove(QLatin1String("%1/android_rcc_bundle.qrc").arg(assetsDir));
- QDir{QLatin1String("%1/android_rcc_bundle").arg(assetsDir)}.removeRecursively();
+ QFile::remove("%1/android_rcc_bundle.qrc"_L1.arg(assetsDir));
+ QDir{"%1/android_rcc_bundle"_L1.arg(assetsDir)}.removeRecursively();
}
return res;
}
@@ -2268,9 +2429,17 @@ bool readDependencies(Options *options)
QSet<QString> remainingDependencies;
// Add dependencies of application binary first
- if (!readDependenciesFromElf(options, QLatin1String("%1/libs/%2/lib%3_%2.so").arg(options->outputDirectory, options->currentArchitecture, options->applicationBinary), &usedDependencies, &remainingDependencies))
+ if (!readDependenciesFromElf(options, "%1/libs/%2/lib%3_%2.so"_L1.arg(options->outputDirectory, options->currentArchitecture, options->applicationBinary), &usedDependencies, &remainingDependencies))
return false;
+ QList<QtDependency> pluginDeps;
+ for (const auto &pluginPath : options->androidDeployPlugins) {
+ pluginDeps.append(findFilesRecursively(*options, QFileInfo(pluginPath),
+ options->qtInstallDirectory + "/"_L1));
+ }
+
+ readDependenciesFromFiles(options, pluginDeps, usedDependencies, remainingDependencies);
+
while (!remainingDependencies.isEmpty()) {
QSet<QString>::iterator start = remainingDependencies.begin();
QString fileName = absoluteFilePath(options, *start);
@@ -2284,7 +2453,7 @@ bool readDependencies(Options *options)
} else {
fprintf(stdout, "Skipping %s due to unmet dependencies: %s\n",
qPrintable(fileName),
- qPrintable(unmetDependencies.join(QLatin1Char(','))));
+ qPrintable(unmetDependencies.join(u',')));
}
}
@@ -2294,18 +2463,17 @@ bool readDependencies(Options *options)
if (!goodToCopy(options, absoluteFilePath(options, *it), &unmetDependencies)) {
fprintf(stdout, "Skipping %s due to unmet dependencies: %s\n",
qPrintable(*it),
- qPrintable(unmetDependencies.join(QLatin1Char(','))));
+ qPrintable(unmetDependencies.join(u',')));
it = options->localLibs[options->currentArchitecture].erase(it);
} else {
++it;
}
}
- if ((!options->rootPaths.empty() || options->qrcFiles.isEmpty()) &&
- !scanImports(options, &usedDependencies))
- return false;
-
- return true;
+ if (options->qmlSkipImportScanning
+ || (options->rootPaths.empty() && options->qrcFiles.isEmpty()))
+ return true;
+ return scanImports(options, &usedDependencies);
}
bool containsApplicationBinary(Options *options)
@@ -2316,18 +2484,17 @@ bool containsApplicationBinary(Options *options)
if (options->verbose)
fprintf(stdout, "Checking if application binary is in package.\n");
- QFileInfo applicationBinary(options->applicationBinary);
- QString applicationFileName = QLatin1String("lib%1_%2.so").arg(options->applicationBinary,
- options->currentArchitecture);
+ QString applicationFileName = "lib%1_%2.so"_L1.arg(options->applicationBinary,
+ options->currentArchitecture);
- QString applicationPath = QLatin1String("%1/libs/%2/%3").arg(options->outputDirectory,
- options->currentArchitecture,
- applicationFileName);
+ QString applicationPath = "%1/libs/%2/%3"_L1.arg(options->outputDirectory,
+ options->currentArchitecture,
+ applicationFileName);
if (!QFile::exists(applicationPath)) {
#if defined(Q_OS_WIN32)
- QLatin1String makeTool("mingw32-make"); // Only Mingw host builds supported on Windows currently
+ const auto makeTool = "mingw32-make"_L1; // Only Mingw host builds supported on Windows currently
#else
- QLatin1String makeTool("make");
+ const auto makeTool = "make"_L1;
#endif
fprintf(stderr, "Application binary is not in output directory: %s. Please run '%s install INSTALL_ROOT=%s' first.\n",
qPrintable(applicationFileName),
@@ -2340,20 +2507,16 @@ bool containsApplicationBinary(Options *options)
FILE *runAdb(const Options &options, const QString &arguments)
{
- QString adb = options.sdkPath + QLatin1String("/platform-tools/adb");
-#if defined(Q_OS_WIN32)
- adb += QLatin1String(".exe");
-#endif
-
+ QString adb = execSuffixAppended(options.sdkPath + "/platform-tools/adb"_L1);
if (!QFile::exists(adb)) {
fprintf(stderr, "Cannot find adb tool: %s\n", qPrintable(adb));
return 0;
}
QString installOption;
if (!options.installLocation.isEmpty())
- installOption = QLatin1String(" -s ") + shellQuote(options.installLocation);
+ installOption = " -s "_L1 + shellQuote(options.installLocation);
- adb = QLatin1String("%1%2 %3").arg(shellQuote(adb), installOption, arguments);
+ adb = "%1%2 %3"_L1.arg(shellQuote(adb), installOption, arguments);
if (options.verbose)
fprintf(stdout, "Running command \"%s\"\n", adb.toLocal8Bit().constData());
@@ -2369,7 +2532,7 @@ FILE *runAdb(const Options &options, const QString &arguments)
bool goodToCopy(const Options *options, const QString &file, QStringList *unmetDependencies)
{
- if (!file.endsWith(QLatin1String(".so")))
+ if (!file.endsWith(".so"_L1))
return true;
if (!checkArchitecture(*options, file))
@@ -2394,6 +2557,10 @@ bool copyQtFiles(Options *options)
case Options::Bundled:
fprintf(stdout, "Copying %zd dependencies from Qt into package.\n", size_t(options->qtDependencies[options->currentArchitecture].size()));
break;
+ case Options::Unbundled:
+ fprintf(stdout, "Copying dependencies from Qt into the package build folder,"
+ "skipping native libraries.\n");
+ break;
};
}
@@ -2401,23 +2568,19 @@ bool copyQtFiles(Options *options)
return true;
- QString libsDirectory = QLatin1String("libs/");
+ QString libsDirectory = "libs/"_L1;
// Copy other Qt dependencies
- auto assetsDestinationDirectory = QLatin1String("assets/android_rcc_bundle/");
- for (const QtDependency &qtDependency : qAsConst(options->qtDependencies[options->currentArchitecture])) {
+ auto assetsDestinationDirectory = "assets/android_rcc_bundle/"_L1;
+ for (const QtDependency &qtDependency : std::as_const(options->qtDependencies[options->currentArchitecture])) {
QString sourceFileName = qtDependency.absolutePath;
QString destinationFileName;
-
- if (qtDependency.relativePath.endsWith(QLatin1String(".so"))) {
- QString garbledFileName;
- if (QDir::fromNativeSeparators(qtDependency.relativePath).startsWith(QLatin1String("lib/"))) {
- garbledFileName = qtDependency.relativePath.mid(sizeof("lib/") - 1);
- } else {
- garbledFileName = qtDependency.relativePath.mid(qtDependency.relativePath.lastIndexOf(QLatin1Char('/')) + 1);
- }
- destinationFileName = libsDirectory + options->currentArchitecture + QLatin1Char('/') + garbledFileName;
- } else if (QDir::fromNativeSeparators(qtDependency.relativePath).startsWith(QLatin1String("jar/"))) {
+ bool isSharedLibrary = qtDependency.relativePath.endsWith(".so"_L1);
+ if (isSharedLibrary) {
+ QString garbledFileName = qtDependency.relativePath.mid(
+ qtDependency.relativePath.lastIndexOf(u'/') + 1);
+ destinationFileName = libsDirectory + options->currentArchitecture + u'/' + garbledFileName;
+ } else if (QDir::fromNativeSeparators(qtDependency.relativePath).startsWith("jar/"_L1)) {
destinationFileName = libsDirectory + qtDependency.relativePath.mid(sizeof("jar/") - 1);
} else {
destinationFileName = assetsDestinationDirectory + qtDependency.relativePath;
@@ -2438,19 +2601,18 @@ bool copyQtFiles(Options *options)
} else {
fprintf(stdout, " -- Skipping %s. It has unmet dependencies: %s.\n",
qPrintable(sourceFileName),
- qPrintable(unmetDependencies.join(QLatin1Char(','))));
+ qPrintable(unmetDependencies.join(u',')));
}
continue;
}
- if (options->deploymentMechanism == Options::Bundled
+ if ((isDeployment(options, Options::Bundled) || !isSharedLibrary)
&& !copyFileIfNewer(sourceFileName,
- options->outputDirectory + QLatin1Char('/') + destinationFileName,
+ options->outputDirectory + u'/' + destinationFileName,
*options)) {
return false;
}
-
- options->bundledFiles[options->currentArchitecture] += qMakePair(destinationFileName, qtDependency.relativePath);
+ options->bundledFiles[options->currentArchitecture] += std::make_pair(destinationFileName, qtDependency.relativePath);
}
return true;
@@ -2460,7 +2622,7 @@ QStringList getLibraryProjectsInOutputFolder(const Options &options)
{
QStringList ret;
- QFile file(options.outputDirectory + QLatin1String("/project.properties"));
+ QFile file(options.outputDirectory + "/project.properties"_L1);
if (file.open(QIODevice::ReadOnly)) {
while (!file.atEnd()) {
QByteArray line = file.readLine().trimmed();
@@ -2469,7 +2631,7 @@ QStringList getLibraryProjectsInOutputFolder(const Options &options)
if (equalSignIndex >= 0) {
QString path = QString::fromLocal8Bit(line.mid(equalSignIndex + 1));
- QFileInfo info(options.outputDirectory + QLatin1Char('/') + path);
+ QFileInfo info(options.outputDirectory + u'/' + path);
if (QDir::isRelativePath(path)
&& info.exists()
&& info.isDir()
@@ -2484,63 +2646,6 @@ QStringList getLibraryProjectsInOutputFolder(const Options &options)
return ret;
}
-bool createAndroidProject(const Options &options)
-{
- if (options.verbose)
- fprintf(stdout, "Running Android tool to create package definition.\n");
-
- QString androidToolExecutable = options.sdkPath + QLatin1String("/tools/android");
-#if defined(Q_OS_WIN32)
- androidToolExecutable += QLatin1String(".bat");
-#endif
-
- if (!QFile::exists(androidToolExecutable)) {
- fprintf(stderr, "Cannot find Android tool: %s\n", qPrintable(androidToolExecutable));
- return false;
- }
-
- QString androidTool = QLatin1String("%1 update project --path %2 --target %3 --name QtApp")
- .arg(shellQuote(androidToolExecutable))
- .arg(shellQuote(options.outputDirectory))
- .arg(shellQuote(options.androidPlatform));
-
- if (options.verbose)
- fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool));
-
- FILE *androidToolCommand = openProcess(androidTool);
- if (androidToolCommand == 0) {
- fprintf(stderr, "Cannot run command '%s'\n", qPrintable(androidTool));
- return false;
- }
-
- pclose(androidToolCommand);
-
- // If the project has subprojects inside the current folder, we need to also run android update on these.
- const QStringList libraryProjects = getLibraryProjectsInOutputFolder(options);
- for (const QString &libraryProject : libraryProjects) {
- if (options.verbose)
- fprintf(stdout, "Updating subproject %s\n", qPrintable(libraryProject));
-
- androidTool = QLatin1String("%1 update lib-project --path %2 --target %3")
- .arg(shellQuote(androidToolExecutable))
- .arg(shellQuote(libraryProject))
- .arg(shellQuote(options.androidPlatform));
-
- if (options.verbose)
- fprintf(stdout, " -- Command: %s\n", qPrintable(androidTool));
-
- FILE *androidToolCommand = popen(androidTool.toLocal8Bit().constData(), QT_POPEN_READ);
- if (androidToolCommand == 0) {
- fprintf(stderr, "Cannot run command '%s'\n", qPrintable(androidTool));
- return false;
- }
-
- pclose(androidToolCommand);
- }
-
- return true;
-}
-
QString findInPath(const QString &fileName)
{
const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
@@ -2552,9 +2657,9 @@ QString findInPath(const QString &fileName)
const QStringList paths = path.split(separator);
for (const QString &path : paths) {
- QFileInfo fileInfo(path + QLatin1Char('/') + fileName);
+ QFileInfo fileInfo(path + u'/' + fileName);
if (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable())
- return path + QLatin1Char('/') + fileName;
+ return path + u'/' + fileName;
}
return QString();
@@ -2584,15 +2689,16 @@ static GradleProperties readGradleProperties(const QString &path)
static bool mergeGradleProperties(const QString &path, GradleProperties properties)
{
- QFile::remove(path + QLatin1Char('~'));
- QFile::rename(path, path + QLatin1Char('~'));
+ const QString oldPathStr = path + u'~';
+ QFile::remove(oldPathStr);
+ QFile::rename(path, oldPathStr);
QFile file(path);
if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text)) {
fprintf(stderr, "Can't open file: %s for writing\n", qPrintable(file.fileName()));
return false;
}
- QFile oldFile(path + QLatin1Char('~'));
+ QFile oldFile(oldPathStr);
if (oldFile.open(QIODevice::ReadOnly)) {
while (!oldFile.atEnd()) {
QByteArray line(oldFile.readLine());
@@ -2605,9 +2711,10 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti
continue;
}
}
- file.write(line);
+ file.write(line.trimmed() + '\n');
}
oldFile.close();
+ QFile::remove(oldPathStr);
}
for (GradleProperties::const_iterator it = properties.begin(); it != properties.end(); ++it)
@@ -2621,11 +2728,11 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti
void checkAndWarnGradleLongPaths(const QString &outputDirectory)
{
QStringList longFileNames;
- QDirIterator it(outputDirectory, QStringList(QStringLiteral("*.java")), QDir::Files,
- QDirIterator::Subdirectories);
- while (it.hasNext()) {
- if (it.next().size() >= MAX_PATH)
- longFileNames.append(it.next());
+ using F = QDirListing::IteratorFlag;
+ for (const auto &dirEntry : QDirListing(outputDirectory, QStringList(u"*.java"_s),
+ QDir::Files, F::Recursive)) {
+ if (dirEntry.size() >= MAX_PATH)
+ longFileNames.append(dirEntry.filePath());
}
if (!longFileNames.isEmpty()) {
@@ -2633,29 +2740,91 @@ void checkAndWarnGradleLongPaths(const QString &outputDirectory)
"The maximum path length that can be processed by Gradle on Windows is %d characters.\n"
"Consider moving your project to reduce its path length.\n"
"The following files have too long paths:\n%s.\n",
- MAX_PATH, qPrintable(longFileNames.join(QLatin1Char('\n'))));
+ MAX_PATH, qPrintable(longFileNames.join(u'\n')));
}
}
#endif
+struct GradleFlags {
+ bool setsLegacyPackaging = false;
+ bool usesIntegerCompileSdkVersion = false;
+};
+
+GradleFlags gradleBuildFlags(const QString &path)
+{
+ GradleFlags flags;
+
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly))
+ return flags;
+
+ auto isComment = [](const QByteArray &line) {
+ const auto trimmed = line.trimmed();
+ return trimmed.startsWith("//") || trimmed.startsWith('*') || trimmed.startsWith("/*");
+ };
+
+ const auto lines = file.readAll().split('\n');
+ for (const auto &line : lines) {
+ if (isComment(line))
+ continue;
+ if (line.contains("useLegacyPackaging")) {
+ flags.setsLegacyPackaging = true;
+ } else if (line.contains("compileSdkVersion androidCompileSdkVersion.toInteger()")) {
+ flags.usesIntegerCompileSdkVersion = true;
+ }
+ }
+
+ return flags;
+}
+
bool buildAndroidProject(const Options &options)
{
GradleProperties localProperties;
localProperties["sdk.dir"] = QDir::fromNativeSeparators(options.sdkPath).toUtf8();
- const QString localPropertiesPath = options.outputDirectory + QLatin1String("local.properties");
+ const QString localPropertiesPath = options.outputDirectory + "local.properties"_L1;
if (!mergeGradleProperties(localPropertiesPath, localProperties))
return false;
- QString gradlePropertiesPath = options.outputDirectory + QLatin1String("gradle.properties");
+ const QString gradlePropertiesPath = options.outputDirectory + "gradle.properties"_L1;
GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
- gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
+
+ const QString gradleBuildFilePath = options.outputDirectory + "build.gradle"_L1;
+ GradleFlags gradleFlags = gradleBuildFlags(gradleBuildFilePath);
+ if (!gradleFlags.setsLegacyPackaging)
+ gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
+
gradleProperties["buildDir"] = "build";
- gradleProperties["qtAndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8();
+ gradleProperties["qtAndroidDir"] =
+ (options.qtInstallDirectory + u'/' + options.qtDataDirectory +
+ "/src/android/java"_L1)
+ .toUtf8();
// The following property "qt5AndroidDir" is only for compatibility.
// Projects using a custom build.gradle file may use this variable.
// ### Qt7: Remove the following line
- gradleProperties["qt5AndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8();
- gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit();
+ gradleProperties["qt5AndroidDir"] =
+ (options.qtInstallDirectory + u'/' + options.qtDataDirectory +
+ "/src/android/java"_L1)
+ .toUtf8();
+
+ QByteArray sdkPlatformVersion;
+ // Provide the integer version only if build.gradle explicitly converts to Integer,
+ // to avoid regression to existing projects that build for sdk platform of form android-xx.
+ if (gradleFlags.usesIntegerCompileSdkVersion) {
+ const QByteArray tmp = options.androidPlatform.split(u'-').last().toLocal8Bit();
+ bool ok;
+ tmp.toInt(&ok);
+ if (ok) {
+ sdkPlatformVersion = tmp;
+ } else {
+ fprintf(stderr, "Warning: Gradle expects SDK platform version to be an integer, "
+ "but the set version is not convertible to an integer.");
+ }
+ }
+
+ if (sdkPlatformVersion.isEmpty())
+ sdkPlatformVersion = options.androidPlatform.toLocal8Bit();
+
+ gradleProperties["androidCompileSdkVersion"] = sdkPlatformVersion;
gradleProperties["qtMinSdkVersion"] = options.minSdkVersion;
gradleProperties["qtTargetSdkVersion"] = options.targetSdkVersion;
gradleProperties["androidNdkVersion"] = options.ndkVersion.toUtf8();
@@ -2673,10 +2842,8 @@ bool buildAndroidProject(const Options &options)
if (!mergeGradleProperties(gradlePropertiesPath, gradleProperties))
return false;
-#if defined(Q_OS_WIN32)
- QString gradlePath(options.outputDirectory + QLatin1String("gradlew.bat"));
-#else
- QString gradlePath(options.outputDirectory + QLatin1String("gradlew"));
+ QString gradlePath = batSuffixAppended(options.outputDirectory + "gradlew"_L1);
+#ifndef Q_OS_WIN32
{
QFile f(gradlePath);
if (!f.setPermissions(f.permissions() | QFileDevice::ExeUser))
@@ -2690,12 +2857,12 @@ bool buildAndroidProject(const Options &options)
return false;
}
- QString commandLine = QLatin1String("%1 %2").arg(shellQuote(gradlePath), options.releasePackage ? QLatin1String(" assembleRelease") : QLatin1String(" assembleDebug"));
+ QString commandLine = "%1 %2"_L1.arg(shellQuote(gradlePath), options.releasePackage ? " assembleRelease"_L1 : " assembleDebug"_L1);
if (options.buildAAB)
- commandLine += QLatin1String(" bundle");
+ commandLine += " bundle"_L1;
if (options.verbose)
- commandLine += QLatin1String(" --info");
+ commandLine += " --info"_L1;
FILE *gradleCommand = openProcess(commandLine);
if (gradleCommand == 0) {
@@ -2735,7 +2902,7 @@ bool uninstallApk(const Options &options)
fprintf(stdout, "Uninstalling old Android package %s if present.\n", qPrintable(options.packageName));
- FILE *adbCommand = runAdb(options, QLatin1String(" uninstall ") + shellQuote(options.packageName));
+ FILE *adbCommand = runAdb(options, " uninstall "_L1 + shellQuote(options.packageName));
if (adbCommand == 0)
return false;
@@ -2766,29 +2933,29 @@ enum PackageType {
QString packagePath(const Options &options, PackageType pt)
{
QString path(options.outputDirectory);
- path += QLatin1String("/build/outputs/%1/").arg(pt >= UnsignedAPK ? QStringLiteral("apk") : QStringLiteral("bundle"));
- QString buildType(options.releasePackage ? QLatin1String("release/") : QLatin1String("debug/"));
+ path += "/build/outputs/%1/"_L1.arg(pt >= UnsignedAPK ? QStringLiteral("apk") : QStringLiteral("bundle"));
+ QString buildType(options.releasePackage ? "release/"_L1 : "debug/"_L1);
if (QDir(path + buildType).exists())
path += buildType;
- path += QDir(options.outputDirectory).dirName() + QLatin1Char('-');
+ path += QDir(options.outputDirectory).dirName() + u'-';
if (options.releasePackage) {
- path += QLatin1String("release-");
+ path += "release-"_L1;
if (pt >= UnsignedAPK) {
if (pt == UnsignedAPK)
- path += QLatin1String("un");
- path += QLatin1String("signed.apk");
+ path += "un"_L1;
+ path += "signed.apk"_L1;
} else {
path.chop(1);
- path += QLatin1String(".aab");
+ path += ".aab"_L1;
}
} else {
- path += QLatin1String("debug");
+ path += "debug"_L1;
if (pt >= UnsignedAPK) {
if (pt == SignedAPK)
- path += QLatin1String("-signed");
- path += QLatin1String(".apk");
+ path += "-signed"_L1;
+ path += ".apk"_L1;
} else {
- path += QLatin1String(".aab");
+ path += ".aab"_L1;
}
}
return path;
@@ -2804,10 +2971,9 @@ bool installApk(const Options &options)
if (options.verbose)
fprintf(stdout, "Installing Android package to device.\n");
- FILE *adbCommand = runAdb(options,
- QLatin1String(" install -r ")
+ FILE *adbCommand = runAdb(options, " install -r "_L1
+ packagePath(options, options.keyStore.isEmpty() ? UnsignedAPK
- : SignedAPK));
+ : SignedAPK));
if (adbCommand == 0)
return false;
@@ -2839,12 +3005,14 @@ bool copyPackage(const Options &options)
bool copyStdCpp(Options *options)
{
+ if (isDeployment(options, Options::Unbundled))
+ return true;
if (options->verbose)
fprintf(stdout, "Copying STL library\n");
const QString triple = options->architectures[options->currentArchitecture].triple;
- const QString stdCppPath = QLatin1String("%1/%2/lib%3.so").arg(options->stdCppPath, triple,
- options->stdCppName);
+ const QString stdCppPath = "%1/%2/lib%3.so"_L1.arg(options->stdCppPath, triple,
+ options->stdCppName);
if (!QFile::exists(stdCppPath)) {
fprintf(stderr, "STL library does not exist at %s\n", qPrintable(stdCppPath));
fflush(stdout);
@@ -2852,13 +3020,29 @@ bool copyStdCpp(Options *options)
return false;
}
- const QString destinationFile = QLatin1String("%1/libs/%2/lib%3.so").arg(options->outputDirectory,
- options->currentArchitecture,
- options->stdCppName);
+ const QString destinationFile = "%1/libs/%2/lib%3.so"_L1.arg(options->outputDirectory,
+ options->currentArchitecture,
+ options->stdCppName);
return copyFileIfNewer(stdCppPath, destinationFile, *options);
}
-bool jarSignerSignPackage(const Options &options)
+static QString zipalignPath(const Options &options, bool *ok)
+{
+ *ok = true;
+ QString zipAlignTool = execSuffixAppended(options.sdkPath + "/tools/zipalign"_L1);
+ if (!QFile::exists(zipAlignTool)) {
+ zipAlignTool = execSuffixAppended(options.sdkPath + "/build-tools/"_L1 +
+ options.sdkBuildToolsVersion + "/zipalign"_L1);
+ if (!QFile::exists(zipAlignTool)) {
+ fprintf(stderr, "zipalign tool not found: %s\n", qPrintable(zipAlignTool));
+ *ok = false;
+ }
+ }
+
+ return zipAlignTool;
+}
+
+bool signAAB(const Options &options)
{
if (options.verbose)
fprintf(stdout, "Signing Android package.\n");
@@ -2868,62 +3052,55 @@ bool jarSignerSignPackage(const Options &options)
if (jdkPath.isEmpty())
jdkPath = QString::fromLocal8Bit(qgetenv("JAVA_HOME"));
-#if defined(Q_OS_WIN32)
- QString jarSignerTool = QLatin1String("jarsigner.exe");
-#else
- QString jarSignerTool = QLatin1String("jarsigner");
-#endif
-
- if (jdkPath.isEmpty() || !QFile::exists(jdkPath + QLatin1String("/bin/") + jarSignerTool))
+ QString jarSignerTool = execSuffixAppended("jarsigner"_L1);
+ if (jdkPath.isEmpty() || !QFile::exists(jdkPath + "/bin/"_L1 + jarSignerTool))
jarSignerTool = findInPath(jarSignerTool);
else
- jarSignerTool = jdkPath + QLatin1String("/bin/") + jarSignerTool;
+ jarSignerTool = jdkPath + "/bin/"_L1 + jarSignerTool;
if (!QFile::exists(jarSignerTool)) {
fprintf(stderr, "Cannot find jarsigner in JAVA_HOME or PATH. Please use --jdk option to pass in the correct path to JDK.\n");
return false;
}
- jarSignerTool = QLatin1String("%1 -sigalg %2 -digestalg %3 -keystore %4")
+ jarSignerTool = "%1 -sigalg %2 -digestalg %3 -keystore %4"_L1
.arg(shellQuote(jarSignerTool), shellQuote(options.sigAlg), shellQuote(options.digestAlg), shellQuote(options.keyStore));
if (!options.keyStorePassword.isEmpty())
- jarSignerTool += QLatin1String(" -storepass %1").arg(shellQuote(options.keyStorePassword));
+ jarSignerTool += " -storepass %1"_L1.arg(shellQuote(options.keyStorePassword));
if (!options.storeType.isEmpty())
- jarSignerTool += QLatin1String(" -storetype %1").arg(shellQuote(options.storeType));
+ jarSignerTool += " -storetype %1"_L1.arg(shellQuote(options.storeType));
if (!options.keyPass.isEmpty())
- jarSignerTool += QLatin1String(" -keypass %1").arg(shellQuote(options.keyPass));
+ jarSignerTool += " -keypass %1"_L1.arg(shellQuote(options.keyPass));
if (!options.sigFile.isEmpty())
- jarSignerTool += QLatin1String(" -sigfile %1").arg(shellQuote(options.sigFile));
+ jarSignerTool += " -sigfile %1"_L1.arg(shellQuote(options.sigFile));
if (!options.signedJar.isEmpty())
- jarSignerTool += QLatin1String(" -signedjar %1").arg(shellQuote(options.signedJar));
+ jarSignerTool += " -signedjar %1"_L1.arg(shellQuote(options.signedJar));
if (!options.tsaUrl.isEmpty())
- jarSignerTool += QLatin1String(" -tsa %1").arg(shellQuote(options.tsaUrl));
+ jarSignerTool += " -tsa %1"_L1.arg(shellQuote(options.tsaUrl));
if (!options.tsaCert.isEmpty())
- jarSignerTool += QLatin1String(" -tsacert %1").arg(shellQuote(options.tsaCert));
+ jarSignerTool += " -tsacert %1"_L1.arg(shellQuote(options.tsaCert));
if (options.internalSf)
- jarSignerTool += QLatin1String(" -internalsf");
+ jarSignerTool += " -internalsf"_L1;
if (options.sectionsOnly)
- jarSignerTool += QLatin1String(" -sectionsonly");
+ jarSignerTool += " -sectionsonly"_L1;
if (options.protectedAuthenticationPath)
- jarSignerTool += QLatin1String(" -protected");
+ jarSignerTool += " -protected"_L1;
- auto signPackage = [&](const QString &file) {
+ auto jarSignPackage = [&](const QString &file) {
fprintf(stdout, "Signing file %s\n", qPrintable(file));
fflush(stdout);
- QString command = jarSignerTool
- + QLatin1String(" %1 %2")
- .arg(shellQuote(file))
- .arg(shellQuote(options.keyStoreAlias));
+ QString command = jarSignerTool + " %1 %2"_L1.arg(shellQuote(file))
+ .arg(shellQuote(options.keyStoreAlias));
FILE *jarSignerCommand = openProcess(command);
if (jarSignerCommand == 0) {
@@ -2947,81 +3124,22 @@ bool jarSignerSignPackage(const Options &options)
return true;
};
- if (!signPackage(packagePath(options, UnsignedAPK)))
- return false;
- if (options.buildAAB && !signPackage(packagePath(options, AAB)))
- return false;
-
- QString zipAlignTool = options.sdkPath + QLatin1String("/tools/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
-
- if (!QFile::exists(zipAlignTool)) {
- zipAlignTool = options.sdkPath + QLatin1String("/build-tools/") + options.sdkBuildToolsVersion + QLatin1String("/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
- if (!QFile::exists(zipAlignTool)) {
- fprintf(stderr, "zipalign tool not found: %s\n", qPrintable(zipAlignTool));
- return false;
- }
- }
-
- zipAlignTool = QLatin1String("%1%2 -f 4 %3 %4")
- .arg(shellQuote(zipAlignTool),
- options.verbose ? QLatin1String(" -v") : QLatin1String(),
- shellQuote(packagePath(options, UnsignedAPK)),
- shellQuote(packagePath(options, SignedAPK)));
-
- FILE *zipAlignCommand = openProcess(zipAlignTool);
- if (zipAlignCommand == 0) {
- fprintf(stderr, "Couldn't run zipalign.\n");
+ if (options.buildAAB && !jarSignPackage(packagePath(options, AAB)))
return false;
- }
-
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), zipAlignCommand) != 0)
- fprintf(stdout, "%s", buffer);
-
- int errorCode = pclose(zipAlignCommand);
- if (errorCode != 0) {
- fprintf(stderr, "zipalign command failed.\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
-
- return QFile::remove(packagePath(options, UnsignedAPK));
+ return true;
}
bool signPackage(const Options &options)
{
- QString apksignerTool = options.sdkPath + QLatin1String("/build-tools/") + options.sdkBuildToolsVersion + QLatin1String("/apksigner");
-#if defined(Q_OS_WIN32)
- apksignerTool += QLatin1String(".bat");
-#endif
-
- if (options.jarSigner || !QFile::exists(apksignerTool))
- return jarSignerSignPackage(options);
+ const QString apksignerTool = batSuffixAppended(options.sdkPath + "/build-tools/"_L1 +
+ options.sdkBuildToolsVersion + "/apksigner"_L1);
+ // APKs signed with apksigner must not be changed after they're signed,
+ // therefore we need to zipalign it before we sign it.
- // APKs signed with apksigner must not be changed after they're signed, therefore we need to zipalign it before we sign it.
-
- QString zipAlignTool = options.sdkPath + QLatin1String("/tools/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
-
- if (!QFile::exists(zipAlignTool)) {
- zipAlignTool = options.sdkPath + QLatin1String("/build-tools/") + options.sdkBuildToolsVersion + QLatin1String("/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
- if (!QFile::exists(zipAlignTool)) {
- fprintf(stderr, "zipalign tool not found: %s\n", qPrintable(zipAlignTool));
- return false;
- }
- }
+ bool ok;
+ QString zipAlignTool = zipalignPath(options, &ok);
+ if (!ok)
+ return false;
auto zipalignRunner = [](const QString &zipAlignCommandLine) {
FILE *zipAlignCommand = openProcess(zipAlignCommandLine);
@@ -3038,9 +3156,9 @@ bool signPackage(const Options &options)
};
const QString verifyZipAlignCommandLine =
- QLatin1String("%1%2 -c 4 %3")
+ "%1%2 -c 4 %3"_L1
.arg(shellQuote(zipAlignTool),
- options.verbose ? QLatin1String(" -v") : QLatin1String(),
+ options.verbose ? " -v"_L1 : QLatin1StringView(),
shellQuote(packagePath(options, UnsignedAPK)));
if (zipalignRunner(verifyZipAlignCommandLine)) {
@@ -3059,9 +3177,9 @@ bool signPackage(const Options &options)
fprintf(stdout, "APK not aligned, aligning it for signing.\n");
const QString zipAlignCommandLine =
- QLatin1String("%1%2 -f 4 %3 %4")
+ "%1%2 -f 4 %3 %4"_L1
.arg(shellQuote(zipAlignTool),
- options.verbose ? QLatin1String(" -v") : QLatin1String(),
+ options.verbose ? " -v"_L1 : QLatin1StringView(),
shellQuote(packagePath(options, UnsignedAPK)),
shellQuote(packagePath(options, SignedAPK)));
@@ -3073,22 +3191,22 @@ bool signPackage(const Options &options)
}
}
- QString apkSignCommand = QLatin1String("%1 sign --ks %2")
+ QString apkSignCommand = "%1 sign --ks %2"_L1
.arg(shellQuote(apksignerTool), shellQuote(options.keyStore));
if (!options.keyStorePassword.isEmpty())
- apkSignCommand += QLatin1String(" --ks-pass pass:%1").arg(shellQuote(options.keyStorePassword));
+ apkSignCommand += " --ks-pass pass:%1"_L1.arg(shellQuote(options.keyStorePassword));
if (!options.keyStoreAlias.isEmpty())
- apkSignCommand += QLatin1String(" --ks-key-alias %1").arg(shellQuote(options.keyStoreAlias));
+ apkSignCommand += " --ks-key-alias %1"_L1.arg(shellQuote(options.keyStoreAlias));
if (!options.keyPass.isEmpty())
- apkSignCommand += QLatin1String(" --key-pass pass:%1").arg(shellQuote(options.keyPass));
+ apkSignCommand += " --key-pass pass:%1"_L1.arg(shellQuote(options.keyPass));
if (options.verbose)
- apkSignCommand += QLatin1String(" --verbose");
+ apkSignCommand += " --verbose"_L1;
- apkSignCommand += QLatin1String(" %1").arg(shellQuote(packagePath(options, SignedAPK)));
+ apkSignCommand += " %1"_L1.arg(shellQuote(packagePath(options, SignedAPK)));
auto apkSignerRunner = [](const QString &command, bool verbose) {
FILE *apkSigner = openProcess(command);
@@ -3116,9 +3234,12 @@ bool signPackage(const Options &options)
return false;
const QString apkVerifyCommand =
- QLatin1String("%1 verify --verbose %2")
+ "%1 verify --verbose %2"_L1
.arg(shellQuote(apksignerTool), shellQuote(packagePath(options, SignedAPK)));
+ if (options.buildAAB && !signAAB(options))
+ return false;
+
// Verify the package and remove the unsigned apk
return apkSignerRunner(apkVerifyCommand, true) && QFile::remove(packagePath(options, UnsignedAPK));
}
@@ -3136,7 +3257,7 @@ enum ErrorCode
CannotCopyAndroidExtraLibs = 10,
CannotCopyAndroidSources = 11,
CannotUpdateAndroidFiles = 12,
- CannotCreateAndroidProject = 13,
+ CannotCreateAndroidProject = 13, // Not used anymore
CannotBuildAndroidProject = 14,
CannotSignPackage = 15,
CannotInstallApk = 16,
@@ -3154,7 +3275,7 @@ bool writeDependencyFile(const Options &options)
if (options.copyDependenciesOnly) {
// When androiddeploy Qt is running in copyDependenciesOnly mode we need to use
// the timestamp file as the target to collect dependencies.
- QString timestampAbsPath = QFileInfo(options.depFilePath).absolutePath() + QLatin1String("/timestamp");
+ QString timestampAbsPath = QFileInfo(options.depFilePath).absolutePath() + "/timestamp"_L1;
relativeTargetPath = QDir(options.buildDirectory).relativeFilePath(timestampAbsPath);
} else {
relativeTargetPath = QDir(options.buildDirectory).relativeFilePath(options.apkPath);
@@ -3194,7 +3315,6 @@ int main(int argc, char *argv[])
fprintf(stdout, "[TIMING] %lld ns: Read input file\n", options.timer.nsecsElapsed());
fprintf(stdout,
-// "012345678901234567890123456789012345678901234567890123456789012345678901"
"Generating Android Package\n"
" Input file: %s\n"
" Output directory: %s\n"
@@ -3215,10 +3335,12 @@ int main(int argc, char *argv[])
for (auto it = options.architectures.constBegin(); it != options.architectures.constEnd(); ++it) {
if (!it->enabled)
continue;
- options.setCurrentQtArchitecture(it.key(), it.value().qtInstallDirectory);
+ options.setCurrentQtArchitecture(it.key(),
+ it.value().qtInstallDirectory,
+ it.value().qtDirectories);
// All architectures have a copy of the gradle files but only one set needs to be copied.
- if (!androidTemplatetCopied && options.build && !options.auxMode && !options.copyDependenciesOnly) {
+ if (!androidTemplatetCopied && options.build && !options.copyDependenciesOnly) {
cleanAndroidFiles(options);
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %lld ns: Cleaned Android file\n", options.timer.nsecsElapsed());
@@ -3255,16 +3377,22 @@ int main(int argc, char *argv[])
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %lld ns: Copied extra resources\n", options.timer.nsecsElapsed());
- if (!options.auxMode) {
- if (!copyStdCpp(&options))
- return CannotCopyGnuStl;
-
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %lld ns: Copied GNU STL\n", options.timer.nsecsElapsed());
- }
+ if (!copyStdCpp(&options))
+ return CannotCopyGnuStl;
- if (!containsApplicationBinary(&options))
+ if (Q_UNLIKELY(options.timing))
+ fprintf(stdout, "[TIMING] %lld ns: Copied GNU STL\n", options.timer.nsecsElapsed());
+
+ // If Unbundled deployment is used, remove app lib as we don't want it packaged inside the APK
+ if (options.deploymentMechanism == Options::Unbundled) {
+ QString appLibPath = "%1/libs/%2/lib%3_%2.so"_L1.
+ arg(options.outputDirectory,
+ options.currentArchitecture,
+ options.applicationBinary);
+ QFile::remove(appLibPath);
+ } else if (!containsApplicationBinary(&options)) {
return CannotFindApplicationBinary;
+ }
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %lld ns: Checked for application binary\n", options.timer.nsecsElapsed());
@@ -3288,7 +3416,6 @@ int main(int argc, char *argv[])
return 0;
}
-
if (options.build) {
if (!copyAndroidSources(options))
return CannotCopyAndroidSources;
diff --git a/src/tools/androidtestrunner/CMakeLists.txt b/src/tools/androidtestrunner/CMakeLists.txt
index a078913fbf..7935753cff 100644
--- a/src/tools/androidtestrunner/CMakeLists.txt
+++ b/src/tools/androidtestrunner/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from androidtestrunner.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## androidtestrunner App:
@@ -14,17 +15,14 @@ qt_internal_add_tool(${target_name}
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_FOREACH
- PUBLIC_LIBRARIES
- Qt::Gui
+ LIBRARIES
+ Qt::Core
)
qt_internal_return_unless_building_tools()
set_target_properties(${target_name} PROPERTIES
WIN32_EXECUTABLE FALSE
)
-#### Keys ignored in scope 1:.:.:androidtestrunner.pro:<TRUE>:
-# _OPTION = "host_build"
-
## Scopes:
#####################################################################
diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp
index b6d68882a9..baad678ec0 100644
--- a/src/tools/androidtestrunner/main.cpp
+++ b/src/tools/androidtestrunner/main.cpp
@@ -1,210 +1,200 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 BogDan Vatra <bogdan@kde.org>
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
-
-#include <QCoreApplication>
-#include <QDir>
-#include <QHash>
-#include <QRegularExpression>
-#include <QSystemSemaphore>
-#include <QXmlStreamReader>
-
-#include <algorithm>
-#include <chrono>
+// Copyright (C) 2019 BogDan Vatra <bogdan@kde.org>
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDeadlineTimer>
+#include <QtCore/QDir>
+#include <QtCore/QHash>
+#include <QtCore/QProcess>
+#include <QtCore/QProcessEnvironment>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QSystemSemaphore>
+#include <QtCore/QThread>
+#include <QtCore/QXmlStreamReader>
+
+#include <atomic>
+#include <csignal>
#include <functional>
-#include <thread>
-
-#ifdef Q_CC_MSVC
-#define popen _popen
-#define QT_POPEN_READ "rb"
-#define pclose _pclose
+#if defined(Q_OS_WIN32)
+#include <process.h>
#else
-#define QT_POPEN_READ "r"
+#include <unistd.h>
#endif
-static auto junitChecker = [](const QByteArray &data) -> bool {
+using namespace Qt::StringLiterals;
+
+static bool checkJunit(const QByteArray &data) {
QXmlStreamReader reader{data};
while (!reader.atEnd()) {
reader.readNext();
- if (reader.isStartElement() && reader.name() == QStringLiteral("testcase") &&
- reader.attributes().value(QStringLiteral("result")).toString() == QStringLiteral("fail")) {
+
+ if (!reader.isStartElement())
+ continue;
+
+ if (reader.name() == "error"_L1)
return false;
+
+ const QString type = reader.attributes().value("type"_L1).toString();
+ if (reader.name() == "failure"_L1) {
+ if (type == "fail"_L1 || type == "xpass"_L1)
+ return false;
}
}
+
+ // Fail if there's an error after reading through all the xml output
+ return !reader.hasError();
+}
+
+static bool checkTxt(const QByteArray &data) {
+ if (data.indexOf("\nFAIL! : "_L1) >= 0)
+ return false;
+ if (data.indexOf("\nXPASS : "_L1) >= 0)
+ return false;
+ // Look for "********* Finished testing of tst_QTestName *********"
+ static const QRegularExpression testTail("\\*+ +Finished testing of .+ +\\*+"_L1);
+ return testTail.match(QLatin1StringView(data)).hasMatch();
+}
+
+static bool checkCsv(const QByteArray &data) {
+ // The csv format is only suitable for benchmarks,
+ // so this is not much useful to determine test failure/success.
+ // FIXME: warn the user early on about this.
+ Q_UNUSED(data);
return true;
-};
+}
+
+static bool checkXml(const QByteArray &data) {
+ QXmlStreamReader reader{data};
+ while (!reader.atEnd()) {
+ reader.readNext();
+ const QString type = reader.attributes().value("type"_L1).toString();
+ const bool isIncident = (reader.name() == "Incident"_L1);
+ if (reader.isStartElement() && isIncident) {
+ if (type == "fail"_L1 || type == "xpass"_L1)
+ return false;
+ }
+ }
+
+ // Fail if there's an error after reading through all the xml output
+ return !reader.hasError();
+}
+
+static bool checkLightxml(const QByteArray &data) {
+ // lightxml intentionally skips the root element, which technically makes it
+ // not valid XML. We'll add that ourselves for the purpose of validation.
+ QByteArray newData = data;
+ newData.prepend("<root>");
+ newData.append("</root>");
+ return checkXml(newData);
+}
+
+static bool checkTeamcity(const QByteArray &data) {
+ if (data.indexOf("' message='Failure! |[Loc: ") >= 0)
+ return false;
+ const QList<QByteArray> lines = data.trimmed().split('\n');
+ if (lines.isEmpty())
+ return false;
+ return lines.last().startsWith("##teamcity[testSuiteFinished "_L1);
+}
+
+static bool checkTap(const QByteArray &data) {
+ // This will still report blacklisted fails because QTest with TAP
+ // is not putting any data about that.
+ if (data.indexOf("\nnot ok ") >= 0)
+ return false;
+
+ static const QRegularExpression testTail("ok [0-9]* - cleanupTestCase\\(\\)"_L1);
+ return testTail.match(QLatin1StringView(data)).hasMatch();
+}
struct Options
{
bool helpRequested = false;
bool verbose = false;
bool skipAddInstallRoot = false;
- std::chrono::seconds timeout{300}; // 5minutes
+ int timeoutSecs = 600; // 10 minutes
QString buildPath;
- QString adbCommand{QStringLiteral("adb")};
+ QString adbCommand{"adb"_L1};
QString makeCommand;
QString package;
QString activity;
QStringList testArgsList;
QHash<QString, QString> outFiles;
- QString testArgs;
+ QStringList amStarttestArgs;
QString apkPath;
- int sdkVersion = -1;
- int pid = -1;
+ QString ndkStackPath;
bool showLogcatOutput = false;
- QHash<QString, std::function<bool(const QByteArray &)>> checkFiles = {
- {QStringLiteral("txt"), [](const QByteArray &data) -> bool {
- return data.indexOf("\nFAIL! : ") < 0;
- }},
- {QStringLiteral("csv"), [](const QByteArray &/*data*/) -> bool {
- // It seems csv is broken
- return true;
- }},
- {QStringLiteral("xml"), [](const QByteArray &data) -> bool {
- QXmlStreamReader reader{data};
- while (!reader.atEnd()) {
- reader.readNext();
- if (reader.isStartElement() && reader.name() == QStringLiteral("Incident") &&
- reader.attributes().value(QStringLiteral("type")).toString() == QStringLiteral("fail")) {
- return false;
- }
- }
- return true;
- }},
- {QStringLiteral("lightxml"), [](const QByteArray &data) -> bool {
- return data.indexOf("\n<Incident type=\"fail\" ") < 0;
- }},
- {QStringLiteral("xunitxml"), junitChecker},
- {QStringLiteral("junitxml"), junitChecker},
- {QStringLiteral("teamcity"), [](const QByteArray &data) -> bool {
- return data.indexOf("' message='Failure! |[Loc: ") < 0;
- }},
- {QStringLiteral("tap"), [](const QByteArray &data) -> bool {
- return data.indexOf("\nnot ok ") < 0;
- }},
+ const QHash<QString, std::function<bool(const QByteArray &)>> checkFiles = {
+ {"txt"_L1, checkTxt},
+ {"csv"_L1, checkCsv},
+ {"xml"_L1, checkXml},
+ {"lightxml"_L1, checkLightxml},
+ {"xunitxml"_L1, checkJunit},
+ {"junitxml"_L1, checkJunit},
+ {"teamcity"_L1, checkTeamcity},
+ {"tap"_L1, checkTap},
};
};
static Options g_options;
-static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = false)
+struct TestInfo
{
- if (verbose)
- fprintf(stdout, "Execute %s.\n", command.toUtf8().constData());
- FILE *process = popen(command.toUtf8().constData(), QT_POPEN_READ);
-
- if (!process) {
- fprintf(stderr, "Cannot execute command %s.\n", qPrintable(command));
- return false;
- }
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), process)) {
- if (output)
- output->append(buffer);
- if (verbose)
- fprintf(stdout, "%s", buffer);
- }
+ int sdkVersion = -1;
+ int pid = -1;
- fflush(stdout);
- fflush(stderr);
+ std::atomic<bool> isPackageInstalled { false };
+ std::atomic<bool> isTestRunnerInterrupted { false };
+};
- return pclose(process) == 0;
-}
+static TestInfo g_testInfo;
-// Copy-pasted from qmake/library/ioutil.cpp
-inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
+static bool execCommand(const QString &program, const QStringList &args,
+ QByteArray *output = nullptr, bool verbose = false)
{
- for (int x = arg.length() - 1; x >= 0; --x) {
- ushort c = arg.unicode()[x].unicode();
- if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
- return true;
- }
- return false;
-}
+ const auto command = program + " "_L1 + args.join(u' ');
-static QString shellQuoteUnix(const QString &arg)
-{
- // Chars that should be quoted (TM). This includes:
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
- 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
- }; // 0-32 \'"$`<>|;&(){}*?#!~[]
+ if (verbose && g_options.verbose)
+ qDebug("Execute %s.", command.toUtf8().constData());
- if (!arg.length())
- return QStringLiteral("\"\"");
+ QProcess process;
+ process.start(program, args);
+ if (!process.waitForStarted()) {
+ qCritical("Cannot execute command %s.", qPrintable(command));
+ return false;
+ }
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- ret.replace(QLatin1Char('\''), QStringLiteral("'\\''"));
- ret.prepend(QLatin1Char('\''));
- ret.append(QLatin1Char('\''));
+ // If the command is not adb, for example, make or ninja, it can take more that
+ // QProcess::waitForFinished() 30 secs, so for that use a higher timeout.
+ const int FinishTimeout = program.endsWith("adb"_L1) ? 30000 : g_options.timeoutSecs * 1000;
+ if (!process.waitForFinished(FinishTimeout)) {
+ qCritical("Execution of command %s timed out.", qPrintable(command));
+ return false;
}
- return ret;
+
+ const auto stdOut = process.readAllStandardOutput();
+ if (output)
+ output->append(stdOut);
+
+ if (verbose && g_options.verbose)
+ qDebug() << stdOut.constData();
+
+ return process.exitCode() == 0;
}
-static QString shellQuoteWin(const QString &arg)
+static bool execAdbCommand(const QStringList &args, QByteArray *output = nullptr,
+ bool verbose = true)
{
- // Chars that should be quoted (TM). This includes:
- // - control chars & space
- // - the shell meta chars "&()<>^|
- // - the potential separators ,;=
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
- };
-
- if (!arg.length())
- return QStringLiteral("\"\"");
-
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- // Quotes are escaped and their preceding backslashes are doubled.
- // It's impossible to escape anything inside a quoted string on cmd
- // level, so the outer quoting must be "suspended".
- ret.replace(QRegularExpression(QStringLiteral("(\\\\*)\"")), QStringLiteral("\"\\1\\1\\^\"\""));
- // The argument must not end with a \ since this would be interpreted
- // as escaping the quote -- rather put the \ behind the quote: e.g.
- // rather use "foo"\ than "foo\"
- int i = ret.length();
- while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
- --i;
- ret.insert(i, QLatin1Char('"'));
- ret.prepend(QLatin1Char('"'));
- }
- return ret;
+ return execCommand(g_options.adbCommand, args, output, verbose);
}
-static QString shellQuote(const QString &arg)
+static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = true)
{
- if (QDir::separator() == QLatin1Char('\\'))
- return shellQuoteWin(arg);
- else
- return shellQuoteUnix(arg);
+ auto args = QProcess::splitCommand(command);
+ const auto program = args.first();
+ args.removeOne(program);
+ return execCommand(program, args, output, verbose);
}
static bool parseOptions()
@@ -213,45 +203,50 @@ static bool parseOptions()
int i = 1;
for (; i < arguments.size(); ++i) {
const QString &argument = arguments.at(i);
- if (argument.compare(QStringLiteral("--adb"), Qt::CaseInsensitive) == 0) {
+ if (argument.compare("--adb"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
g_options.helpRequested = true;
else
g_options.adbCommand = arguments.at(++i);
- } else if (argument.compare(QStringLiteral("--path"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--path"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
g_options.helpRequested = true;
else
g_options.buildPath = arguments.at(++i);
- } else if (argument.compare(QStringLiteral("--make"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--make"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
g_options.helpRequested = true;
else
g_options.makeCommand = arguments.at(++i);
- } else if (argument.compare(QStringLiteral("--apk"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--apk"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
g_options.helpRequested = true;
else
g_options.apkPath = arguments.at(++i);
- } else if (argument.compare(QStringLiteral("--activity"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--activity"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
g_options.helpRequested = true;
else
g_options.activity = arguments.at(++i);
- } else if (argument.compare(QStringLiteral("--skip-install-root"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--skip-install-root"_L1, Qt::CaseInsensitive) == 0) {
g_options.skipAddInstallRoot = true;
- } else if (argument.compare(QStringLiteral("--show-logcat"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--show-logcat"_L1, Qt::CaseInsensitive) == 0) {
g_options.showLogcatOutput = true;
- } else if (argument.compare(QStringLiteral("--timeout"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--ndk-stack"_L1, Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.ndkStackPath = arguments.at(++i);
+ } else if (argument.compare("--timeout"_L1, Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
g_options.helpRequested = true;
else
- g_options.timeout = std::chrono::seconds{arguments.at(++i).toInt()};
- } else if (argument.compare(QStringLiteral("--help"), Qt::CaseInsensitive) == 0) {
+ g_options.timeoutSecs = arguments.at(++i).toInt();
+ } else if (argument.compare("--help"_L1, Qt::CaseInsensitive) == 0) {
g_options.helpRequested = true;
- } else if (argument.compare(QStringLiteral("--verbose"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--verbose"_L1, Qt::CaseInsensitive) == 0) {
g_options.verbose = true;
- } else if (argument.compare(QStringLiteral("--"), Qt::CaseInsensitive) == 0) {
+ } else if (argument.compare("--"_L1, Qt::CaseInsensitive) == 0) {
++i;
break;
} else {
@@ -266,17 +261,24 @@ static bool parseOptions()
QString serial = qEnvironmentVariable("ANDROID_DEVICE_SERIAL");
if (!serial.isEmpty())
- g_options.adbCommand += QStringLiteral(" -s %1").arg(serial);
+ g_options.adbCommand += " -s %1"_L1.arg(serial);
+
+ if (g_options.ndkStackPath.isEmpty()) {
+ const QString ndkPath = qEnvironmentVariable("ANDROID_NDK_ROOT");
+ const QString ndkStackPath = ndkPath + QDir::separator() + "ndk-stack"_L1;
+ if (QFile::exists(ndkStackPath))
+ g_options.ndkStackPath = ndkStackPath;
+ }
+
return true;
}
static void printHelp()
-{// "012345678901234567890123456789012345678901234567890123456789012345678901"
- fprintf(stderr, "Syntax: %s <options> -- [TESTARGS] \n"
+{
+ qWarning( "Syntax: %s <options> -- [TESTARGS] \n"
"\n"
- " Creates an Android package in a temp directory <destination> and\n"
- " runs it on the default emulator/device or on the one specified by\n"
- " \"ANDROID_DEVICE_SERIAL\" environment variable.\n"
+ " Runs an Android test on the default emulator/device or on the one\n"
+ " specified by \"ANDROID_DEVICE_SERIAL\" environment variable.\n"
"\n"
" Mandatory arguments:\n"
" --path <path>: The path where androiddeployqt builds the android package.\n"
@@ -286,7 +288,7 @@ static void printHelp()
"\n"
" Optional arguments:\n"
" --make <make cmd>: make command, needed to install the qt library.\n"
- " For Qt 5.14+ this can be \"make apk\".\n"
+ " For Qt 6, this can be \"cmake --build . --target <target>_make_apk\".\n"
"\n"
" --adb <adb cmd>: The Android ADB command. If missing the one from\n"
" $PATH will be used.\n"
@@ -294,17 +296,20 @@ static void printHelp()
" --activity <acitvity>: The Activity to run. If missing the first\n"
" activity from AndroidManifest.qml file will be used.\n"
"\n"
- " --timeout <seconds>: Timeout to run the test. Default is 5 minutes.\n"
+ " --timeout <seconds>: Timeout to run the test. Default is 10 minutes.\n"
"\n"
" --skip-install-root: Do not append INSTALL_ROOT=... to the make command.\n"
"\n"
" --show-logcat: Print Logcat output to stdout.\n"
"\n"
+ " --ndk-stack: Path to ndk-stack tool that symbolizes crash stacktraces.\n"
+ " By default, ANDROID_NDK_ROOT env var is used to deduce the tool path.\n"
+ "\n"
" -- Arguments that will be passed to the test application.\n"
"\n"
" --verbose: Prints out information during processing.\n"
"\n"
- " --help: Displays this information.\n\n",
+ " --help: Displays this information.\n",
qPrintable(QCoreApplication::arguments().at(0))
);
}
@@ -316,8 +321,8 @@ static QString packageNameFromAndroidManifest(const QString &androidManifestPath
QXmlStreamReader reader(&androidManifestXml);
while (!reader.atEnd()) {
reader.readNext();
- if (reader.isStartElement() && reader.name() == QStringLiteral("manifest"))
- return reader.attributes().value(QStringLiteral("package")).toString();
+ if (reader.isStartElement() && reader.name() == "manifest"_L1)
+ return reader.attributes().value("package"_L1).toString();
}
}
return {};
@@ -330,8 +335,8 @@ static QString activityFromAndroidManifest(const QString &androidManifestPath)
QXmlStreamReader reader(&androidManifestXml);
while (!reader.atEnd()) {
reader.readNext();
- if (reader.isStartElement() && reader.name() == QStringLiteral("activity"))
- return reader.attributes().value(QStringLiteral("android:name")).toString();
+ if (reader.isStartElement() && reader.name() == "activity"_L1)
+ return reader.attributes().value("android:name"_L1).toString();
}
}
return {};
@@ -340,26 +345,26 @@ static QString activityFromAndroidManifest(const QString &androidManifestPath)
static void setOutputFile(QString file, QString format)
{
if (file.isEmpty())
- file = QStringLiteral("-");
+ file = "-"_L1;
if (format.isEmpty())
- format = QStringLiteral("txt");
+ format = "txt"_L1;
g_options.outFiles[format] = file;
}
static bool parseTestArgs()
{
- QRegularExpression oldFormats{QStringLiteral("^-(txt|csv|xunitxml|junitxml|xml|lightxml|teamcity|tap)$")};
- QRegularExpression newLoggingFormat{QStringLiteral("^(.*),(txt|csv|xunitxml|junitxml|xml|lightxml|teamcity|tap)$")};
+ QRegularExpression oldFormats{"^-(txt|csv|xunitxml|junitxml|xml|lightxml|teamcity|tap)$"_L1};
+ QRegularExpression newLoggingFormat{"^(.*),(txt|csv|xunitxml|junitxml|xml|lightxml|teamcity|tap)$"_L1};
QString file;
QString logType;
- QString unhandledArgs;
+ QStringList unhandledArgs;
for (int i = 0; i < g_options.testArgsList.size(); ++i) {
const QString &arg = g_options.testArgsList[i].trimmed();
- if (arg == QStringLiteral("--"))
+ if (arg == "--"_L1)
continue;
- if (arg == QStringLiteral("-o")) {
+ if (arg == "-o"_L1) {
if (i >= g_options.testArgsList.size() - 1)
return false; // missing file argument
@@ -376,115 +381,157 @@ static bool parseTestArgs()
if (match.hasMatch()) {
logType = match.capturedTexts().at(1);
} else {
- unhandledArgs += QStringLiteral(" %1").arg(arg);
+ // Use triple literal quotes so that QProcess::splitCommand() in androidjnimain.cpp
+ // keeps quotes characters inside the string.
+ QString quotedArg = QString(arg).replace("\""_L1, "\\\"\\\"\\\""_L1);
+ // Escape single quotes so they don't interfere with the shell command,
+ // and so they get passed to the app as single quote inside the string.
+ quotedArg.replace("'"_L1, "\'"_L1);
+ // Add escaped double quote character so that args with spaces are treated as one.
+ unhandledArgs << " \\\"%1\\\""_L1.arg(quotedArg);
}
}
}
if (g_options.outFiles.isEmpty() || !file.isEmpty() || !logType.isEmpty())
setOutputFile(file, logType);
+ QString testAppArgs;
for (const auto &format : g_options.outFiles.keys())
- g_options.testArgs += QStringLiteral(" -o output.%1,%1").arg(format);
+ testAppArgs += "-o output.%1,%1 "_L1.arg(format);
+
+ testAppArgs += unhandledArgs.join(u' ').trimmed();
+ testAppArgs = "\"%1\""_L1.arg(testAppArgs.trimmed());
+ const QString activityName = "%1/%2"_L1.arg(g_options.package).arg(g_options.activity);
+
+ // Pass over any testlib env vars if set
+ QString testEnvVars;
+ const QStringList envVarsList = QProcessEnvironment::systemEnvironment().toStringList();
+ for (const QString &var : envVarsList) {
+ if (var.startsWith("QTEST_"_L1))
+ testEnvVars += "%1 "_L1.arg(var);
+ }
+
+ if (!testEnvVars.isEmpty()) {
+ testEnvVars = QString::fromUtf8(testEnvVars.trimmed().toUtf8().toBase64());
+ testEnvVars = "-e extraenvvars \"%4\""_L1.arg(testEnvVars);
+ }
+
+ g_options.amStarttestArgs = { "shell"_L1, "am"_L1, "start"_L1,
+ "-n"_L1, activityName,
+ "-e"_L1, "applicationArguments"_L1, testAppArgs,
+ testEnvVars
+ };
- g_options.testArgs += unhandledArgs;
- g_options.testArgs = QStringLiteral("shell am start -e applicationArguments \\\"%1\\\" -n %2/%3").arg(shellQuote(g_options.testArgs.trimmed()),
- g_options.package,
- g_options.activity);
return true;
}
-static bool isRunning() {
+static bool obtainPid() {
QByteArray output;
- if (!execCommand(QStringLiteral("%1 shell \"ps | grep ' %2'\"").arg(g_options.adbCommand,
- shellQuote(g_options.package)), &output)) {
+ const QStringList psArgs = { "shell"_L1, "ps | grep ' %1'"_L1.arg(g_options.package) };
+ if (!execAdbCommand(psArgs, &output, false))
+ return false;
+ const QList<QByteArray> lines = output.split(u'\n');
+ if (lines.size() < 1)
return false;
- }
- return output.indexOf(QLatin1String(" " + g_options.package.toUtf8())) > -1;
-}
-static bool waitToFinish()
-{
- using clock = std::chrono::system_clock;
- auto start = clock::now();
- // wait to start
- while (!isRunning()) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- if ((clock::now() - start) > std::chrono::seconds{10})
- return false;
- }
+ QList<QByteArray> columns = lines.first().simplified().replace(u'\t', u' ').split(u' ');
+ if (columns.size() < 3)
+ return false;
- if (g_options.sdkVersion > 23) { // pidof is broken in SDK 23, non-existent before
- QByteArray output;
- const QString command(QStringLiteral("%1 shell pidof -s %2")
- .arg(g_options.adbCommand, shellQuote(g_options.package)));
- execCommand(command, &output, g_options.verbose);
+ if (g_testInfo.pid == -1) {
bool ok = false;
- int pid = output.toInt(&ok); // If we got more than one pid, fail.
- if (ok) {
- g_options.pid = pid;
- } else {
- fprintf(stderr,
- "Unable to obtain the PID of the running unit test. Command \"%s\" "
- "returned \"%s\"\n",
- command.toUtf8().constData(), output.constData());
- fflush(stderr);
- }
+ int pid = columns.at(1).toInt(&ok);
+ if (ok)
+ g_testInfo.pid = pid;
}
- // Wait to finish
- while (isRunning()) {
- std::this_thread::sleep_for(std::chrono::milliseconds(250));
- if ((clock::now() - start) > g_options.timeout)
- return false;
- }
return true;
}
-static void obtainSDKVersion()
+static bool isRunning() {
+ QByteArray output;
+ const QStringList psArgs = { "shell"_L1, "ps | grep ' %1'"_L1.arg(g_options.package) };
+ if (!execAdbCommand(psArgs, &output, false))
+ return false;
+
+ return output.indexOf(QLatin1StringView(" " + g_options.package.toUtf8())) > -1;
+}
+
+static void waitForStartedAndFinished()
+{
+ // wait to start and set PID
+ QDeadlineTimer startDeadline(10000);
+ do {
+ if (obtainPid())
+ break;
+ QThread::msleep(100);
+ } while (!startDeadline.hasExpired() && !g_testInfo.isTestRunnerInterrupted.load());
+
+ // Wait to finish
+ QDeadlineTimer finishedDeadline(g_options.timeoutSecs * 1000);
+ do {
+ if (!isRunning())
+ break;
+ QThread::msleep(250);
+ } while (!finishedDeadline.hasExpired() && !g_testInfo.isTestRunnerInterrupted.load());
+
+ if (finishedDeadline.hasExpired())
+ qWarning() << "Timed out while waiting for the test to finish";
+}
+
+static void obtainSdkVersion()
{
// SDK version is necessary, as in SDK 23 pidof is broken, so we cannot obtain the pid.
// Also, Logcat cannot filter by pid in SDK 23, so we don't offer the --show-logcat option.
QByteArray output;
- const QString command(
- QStringLiteral("%1 shell getprop ro.build.version.sdk").arg(g_options.adbCommand));
- execCommand(command, &output, g_options.verbose);
+ const QStringList versionArgs = { "shell"_L1, "getprop"_L1, "ro.build.version.sdk"_L1 };
+ execAdbCommand(versionArgs, &output, false);
bool ok = false;
int sdkVersion = output.toInt(&ok);
- if (ok) {
- g_options.sdkVersion = sdkVersion;
- } else {
- fprintf(stderr,
- "Unable to obtain the SDK version of the target. Command \"%s\" "
- "returned \"%s\"\n",
- command.toUtf8().constData(), output.constData());
- fflush(stderr);
- }
+ if (ok)
+ g_testInfo.sdkVersion = sdkVersion;
+ else
+ qCritical() << "Unable to obtain the SDK version of the target.";
}
static bool pullFiles()
{
bool ret = true;
+ QByteArray userId;
+ // adb get-current-user command is available starting from API level 26.
+ if (g_testInfo.sdkVersion >= 26) {
+ const QStringList userIdArgs = {"shell"_L1, "cmd"_L1, "activity"_L1, "get-current-user"_L1};
+ if (!execAdbCommand(userIdArgs, &userId, false)) {
+ qCritical() << "Error: failed to retrieve the user ID";
+ return false;
+ }
+ } else {
+ userId = "0";
+ }
+
for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.end(); ++it) {
+ // Get only stdout from cat and get rid of stderr and fail later if the output is empty
+ const QString outSuffix = it.key();
+ const QString catCmd = "cat files/output.%1 2> /dev/null"_L1.arg(outSuffix);
+ const QStringList fullCatArgs = { "shell"_L1, "run-as %1 --user %2 %3"_L1.arg(
+ g_options.package, QString::fromUtf8(userId.simplified()), catCmd) };
+
QByteArray output;
- if (!execCommand(QStringLiteral("%1 shell run-as %2 cat files/output.%3")
- .arg(g_options.adbCommand, g_options.package, it.key()), &output)) {
- // Cannot find output file. Check in path related to current user
- QByteArray userId;
- execCommand(QStringLiteral("%1 shell cmd activity get-current-user")
- .arg(g_options.adbCommand), &userId);
- const QString userIdSimplified(QString::fromUtf8(userId).simplified());
- if (!execCommand(QStringLiteral("%1 shell run-as %2 --user %3 cat files/output.%4")
- .arg(g_options.adbCommand, g_options.package, userIdSimplified, it.key()),
- &output)) {
- return false;
- }
+ if (!execAdbCommand(fullCatArgs, &output, false)) {
+ qCritical() << "Error: failed to retrieve the test's output.%1 file."_L1.arg(outSuffix);
+ return false;
}
- auto checkerIt = g_options.checkFiles.find(it.key());
- ret = ret && checkerIt != g_options.checkFiles.end() && checkerIt.value()(output);
- if (it.value() == QStringLiteral("-")){
- fprintf(stdout, "%s", output.constData());
- fflush(stdout);
+
+ if (output.isEmpty()) {
+ qCritical() << "Error: the test's output.%1 is empty."_L1.arg(outSuffix);
+ return false;
+ }
+
+ auto checkerIt = g_options.checkFiles.find(outSuffix);
+ ret &= (checkerIt != g_options.checkFiles.end() && checkerIt.value()(output));
+ if (it.value() == "-"_L1) {
+ qDebug() << output.constData();
} else {
QFile out{it.value()};
if (!out.open(QIODevice::WriteOnly))
@@ -495,21 +542,171 @@ static bool pullFiles()
return ret;
}
-struct RunnerLocker
+void printLogcat(const QString &formattedTime)
{
- RunnerLocker()
- {
- runner.acquire();
+ QStringList logcatArgs = { "logcat"_L1 };
+ if (g_testInfo.sdkVersion <= 23 || g_testInfo.pid == -1)
+ logcatArgs << "-t"_L1 << formattedTime;
+ else
+ logcatArgs << "-d"_L1 << "--pid=%1"_L1.arg(QString::number(g_testInfo.pid));
+
+ QByteArray logcat;
+ if (!execAdbCommand(logcatArgs, &logcat, false)) {
+ qCritical() << "Error: failed to fetch logcat of the test";
+ return;
+ }
+
+ if (logcat.isEmpty()) {
+ qWarning() << "The retrieved logcat is empty";
+ return;
+ }
+
+ qDebug() << "****** Begin logcat output ******";
+ qDebug().noquote() << logcat;
+ qDebug() << "****** End logcat output ******";
+}
+
+static QString getDeviceABI()
+{
+ const QStringList abiArgs = { "shell"_L1, "getprop"_L1, "ro.product.cpu.abi"_L1 };
+ QByteArray abi;
+ if (!execAdbCommand(abiArgs, &abi, false)) {
+ qWarning() << "Warning: failed to get the device abi, fallback to first libs dir";
+ return {};
+ }
+
+ return QString::fromUtf8(abi.simplified());
+}
+
+void printLogcatCrashBuffer(const QString &formattedTime)
+{
+ bool useNdkStack = false;
+ auto libsPath = "%1/libs/"_L1.arg(g_options.buildPath);
+
+ if (!g_options.ndkStackPath.isEmpty()) {
+ QString abi = getDeviceABI();
+ if (abi.isEmpty()) {
+ QStringList subDirs = QDir(libsPath).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+ if (!subDirs.isEmpty())
+ abi = subDirs.first();
+ }
+
+ if (!abi.isEmpty()) {
+ libsPath += abi;
+ useNdkStack = true;
+ } else {
+ qWarning() << "Warning: failed to get the libs abi, ndk-stack cannot be used.";
+ }
+ } else {
+ qWarning() << "Warning: ndk-stack path not provided and couldn't be deduced "
+ "using the ANDROID_NDK_ROOT environment variable.";
+ }
+
+ QProcess adbCrashProcess;
+ QProcess ndkStackProcess;
+
+ if (useNdkStack) {
+ adbCrashProcess.setStandardOutputProcess(&ndkStackProcess);
+ ndkStackProcess.start(g_options.ndkStackPath, { "-sym"_L1, libsPath });
+ }
+
+ const QStringList adbCrashArgs = { "logcat"_L1, "-b"_L1, "crash"_L1, "-t"_L1, formattedTime };
+ adbCrashProcess.start(g_options.adbCommand, adbCrashArgs);
+
+ if (!adbCrashProcess.waitForStarted()) {
+ qCritical() << "Error: failed to run adb logcat crash command.";
+ return;
}
- ~RunnerLocker()
+
+ if (useNdkStack && !ndkStackProcess.waitForStarted()) {
+ qCritical() << "Error: failed to run ndk-stack command.";
+ return;
+ }
+
+ if (!adbCrashProcess.waitForFinished()) {
+ qCritical() << "Error: adb command timed out.";
+ return;
+ }
+
+ if (useNdkStack && !ndkStackProcess.waitForFinished()) {
+ qCritical() << "Error: ndk-stack command timed out.";
+ return;
+ }
+
+ const QByteArray crash = useNdkStack ? ndkStackProcess.readAllStandardOutput()
+ : adbCrashProcess.readAllStandardOutput();
+ if (crash.isEmpty()) {
+ qWarning() << "The retrieved crash logcat is empty";
+ return;
+ }
+
+ qDebug() << "****** Begin logcat crash buffer output ******";
+ qDebug().noquote() << crash;
+ qDebug() << "****** End logcat crash buffer output ******";
+}
+
+static QString getCurrentTimeString()
+{
+ const QString timeFormat = (g_testInfo.sdkVersion <= 23) ?
+ "%m-%d %H:%M:%S.000"_L1 : "%Y-%m-%d %H:%M:%S.%3N"_L1;
+
+ QStringList dateArgs = { "shell"_L1, "date"_L1, "+'%1'"_L1.arg(timeFormat) };
+ QByteArray output;
+ if (!execAdbCommand(dateArgs, &output, false)) {
+ qWarning() << "Date/time adb command failed";
+ return {};
+ }
+
+ return QString::fromUtf8(output.simplified());
+}
+
+static bool uninstallTestPackage()
+{
+ return execAdbCommand({ "uninstall"_L1, g_options.package }, nullptr);
+}
+
+struct TestRunnerSystemSemaphore
+{
+ TestRunnerSystemSemaphore() { }
+ ~TestRunnerSystemSemaphore() { release(); }
+
+ void acquire() { isAcquired.store(semaphore.acquire()); }
+
+ void release()
{
- runner.release();
+ bool expected = true;
+ // NOTE: There's still could be tiny time gap between the compare_exchange_strong() call
+ // and release() call where the thread could be interrupted, if that's ever an issue,
+ // this code could be checked and improved further.
+ if (isAcquired.compare_exchange_strong(expected, false))
+ isAcquired.store(!semaphore.release());
}
- QSystemSemaphore runner{QStringLiteral("androidtestrunner"), 1, QSystemSemaphore::Open};
+
+ std::atomic<bool> isAcquired { false };
+ QSystemSemaphore semaphore { QSystemSemaphore::platformSafeKey(u"androidtestrunner"_s),
+ 1, QSystemSemaphore::Open };
};
+TestRunnerSystemSemaphore testRunnerLock;
+
+void sigHandler(int signal)
+{
+ std::signal(signal, SIG_DFL);
+ testRunnerLock.release();
+ // Ideally we shouldn't be doing such calls from a signal handler,
+ // and we can't use QSocketNotifier because this tool doesn't spin
+ // a main event loop. Since, there's no other alternative to do this,
+ // let's do the cleanup anyway.
+ if (!g_testInfo.isPackageInstalled.load())
+ _exit(-1);
+ g_testInfo.isTestRunnerInterrupted.store(true);
+}
+
int main(int argc, char *argv[])
{
+ std::signal(SIGINT, sigHandler);
+ std::signal(SIGTERM, sigHandler);
+
QCoreApplication a(argc, argv);
if (!parseOptions()) {
printHelp();
@@ -517,43 +714,33 @@ int main(int argc, char *argv[])
}
if (g_options.makeCommand.isEmpty()) {
- fprintf(stderr,
- "It is required to provide a make command with the \"--make\" parameter "
- "to generate the apk.\n");
+ qCritical() << "It is required to provide a make command with the \"--make\" parameter "
+ "to generate the apk.";
return 1;
}
if (!execCommand(g_options.makeCommand, nullptr, true)) {
if (!g_options.skipAddInstallRoot) {
// we need to run make INSTALL_ROOT=path install to install the application file(s) first
- if (!execCommand(QStringLiteral("%1 INSTALL_ROOT=%2 install")
- .arg(g_options.makeCommand, QDir::toNativeSeparators(g_options.buildPath)), nullptr, g_options.verbose)) {
+ if (!execCommand("%1 INSTALL_ROOT=%2 install"_L1.arg(g_options.makeCommand,
+ QDir::toNativeSeparators(g_options.buildPath)), nullptr)) {
return 1;
}
} else {
- if (!execCommand(QStringLiteral("%1")
- .arg(g_options.makeCommand), nullptr, g_options.verbose)) {
+ if (!execCommand(g_options.makeCommand, nullptr))
return 1;
- }
}
}
if (!QFile::exists(g_options.apkPath)) {
- fprintf(stderr,
- "No apk \"%s\" found after running the make command. Check the provided path and "
- "the make command.\n",
- qPrintable(g_options.apkPath));
+ qCritical("No apk \"%s\" found after running the make command. "
+ "Check the provided path and the make command.",
+ qPrintable(g_options.apkPath));
return 1;
}
- obtainSDKVersion();
-
- RunnerLocker lock; // do not install or run packages while another test is running
- if (!execCommand(QStringLiteral("%1 install -r -g %2")
- .arg(g_options.adbCommand, g_options.apkPath), nullptr, g_options.verbose)) {
- return 1;
- }
+ obtainSdkVersion();
- QString manifest = g_options.buildPath + QStringLiteral("/AndroidManifest.xml");
+ QString manifest = g_options.buildPath + "/AndroidManifest.xml"_L1;
g_options.package = packageNameFromAndroidManifest(manifest);
if (g_options.activity.isEmpty())
g_options.activity = activityFromAndroidManifest(manifest);
@@ -562,30 +749,42 @@ int main(int argc, char *argv[])
if (!parseTestArgs())
return 1;
+ // do not install or run packages while another test is running
+ testRunnerLock.acquire();
+
+ const QStringList installArgs = { "install"_L1, "-r"_L1, "-g"_L1, g_options.apkPath };
+ g_testInfo.isPackageInstalled.store(execAdbCommand(installArgs, nullptr));
+ if (!g_testInfo.isPackageInstalled)
+ return 1;
+
+ const QString formattedTime = getCurrentTimeString();
+
// start the tests
- bool res = execCommand(QStringLiteral("%1 %2").arg(g_options.adbCommand, g_options.testArgs),
- nullptr, g_options.verbose)
- && waitToFinish();
-
- // get logcat output
- if (res && g_options.showLogcatOutput) {
- if (g_options.sdkVersion <= 23) {
- fprintf(stderr, "Cannot show logcat output on Android 23 and below.\n");
- fflush(stderr);
- } else if (g_options.pid > 0) {
- fprintf(stdout, "Logcat output:\n");
- res &= execCommand(QStringLiteral("%1 logcat -d --pid=%2")
- .arg(g_options.adbCommand)
- .arg(g_options.pid),
- nullptr, true);
- fprintf(stdout, "End Logcat output.\n");
- }
+ bool success = execAdbCommand(g_options.amStarttestArgs, nullptr);
+
+ waitForStartedAndFinished();
+
+ if (success) {
+ success &= pullFiles();
+ if (g_options.showLogcatOutput)
+ printLogcat(formattedTime);
+ }
+
+ // If we have a failure, attempt to print both logcat and the crash buffer which
+ // includes the crash stacktrace that is not included in the default logcat.
+ if (!success) {
+ printLogcat(formattedTime);
+ printLogcatCrashBuffer(formattedTime);
+ }
+
+ success &= uninstallTestPackage();
+
+ testRunnerLock.release();
+
+ if (g_testInfo.isTestRunnerInterrupted.load()) {
+ qCritical() << "The androidtestrunner was interrupted and the was test cleaned up.";
+ return 1;
}
- if (res)
- res &= pullFiles();
- res &= execCommand(QStringLiteral("%1 uninstall %2").arg(g_options.adbCommand, g_options.package),
- nullptr, g_options.verbose);
- fflush(stdout);
- return res ? 0 : 1;
+ return success ? 0 : 1;
}
diff --git a/src/tools/bootstrap/CMakeLists.txt b/src/tools/bootstrap/CMakeLists.txt
index 974342ae55..93e826fa22 100644
--- a/src/tools/bootstrap/CMakeLists.txt
+++ b/src/tools/bootstrap/CMakeLists.txt
@@ -1,29 +1,27 @@
-# Generated from bootstrap.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## Bootstrap Module:
#####################################################################
-# special case begin
# The bootstrap library has a few manual tweaks compared to other
# libraries.
qt_add_library(Bootstrap STATIC)
-# special case end
+
+qt_internal_add_sync_header_dependencies(Bootstrap Core)
+
qt_internal_extend_target(Bootstrap
SOURCES
- ../../corelib/global/qendian.cpp
+ ../../corelib/global/qassert.cpp
../../corelib/global/qfloat16.cpp
- ../../corelib/global/qglobal.cpp
../../corelib/global/qlogging.cpp
../../corelib/global/qmalloc.cpp
- ../../corelib/global/qnumeric.cpp
- ../../corelib/global/qoperatingsystemversion.cpp
- ../../corelib/global/qrandom.cpp
+ ../../corelib/global/qtenvironmentvariables.cpp
../../corelib/io/qabstractfileengine.cpp
../../corelib/io/qbuffer.cpp
../../corelib/io/qdebug.cpp
../../corelib/io/qdir.cpp
- ../../corelib/io/qdiriterator.cpp
../../corelib/io/qfile.cpp
../../corelib/io/qfiledevice.cpp
../../corelib/io/qfileinfo.cpp
@@ -32,32 +30,14 @@ qt_internal_extend_target(Bootstrap
../../corelib/io/qfsfileengine.cpp
../../corelib/io/qfsfileengine_iterator.cpp
../../corelib/io/qiodevice.cpp
- ../../corelib/io/qipaddress.cpp
- ../../corelib/io/qloggingcategory.cpp
- ../../corelib/io/qloggingregistry.cpp
- ../../corelib/io/qresource.cpp
- ../../corelib/io/qsavefile.cpp
../../corelib/io/qstandardpaths.cpp
- ../../corelib/io/qtemporarydir.cpp
- ../../corelib/io/qtemporaryfile.cpp
- ../../corelib/io/qurl.cpp
- ../../corelib/io/qurlidna.cpp
- ../../corelib/io/qurlquery.cpp
- ../../corelib/io/qurlrecode.cpp
../../corelib/kernel/qcoreapplication.cpp
- ../../corelib/kernel/qcoreglobaldata.cpp
- ../../corelib/kernel/qiterable.cpp
- ../../corelib/kernel/qmetacontainer.cpp
../../corelib/kernel/qmetatype.cpp
- ../../corelib/kernel/qsharedmemory.cpp
../../corelib/kernel/qsystemerror.cpp
- ../../corelib/kernel/qsystemsemaphore.cpp
- ../../corelib/kernel/qvariant.cpp
../../corelib/plugin/quuid.cpp
../../corelib/serialization/qcborcommon.cpp
../../corelib/serialization/qcborstreamwriter.cpp
../../corelib/serialization/qcborvalue.cpp
- ../../corelib/serialization/qdatastream.cpp
../../corelib/serialization/qjsonarray.cpp
../../corelib/serialization/qjsoncbor.cpp
../../corelib/serialization/qjsondocument.cpp
@@ -66,12 +46,10 @@ qt_internal_extend_target(Bootstrap
../../corelib/serialization/qjsonvalue.cpp
../../corelib/serialization/qjsonwriter.cpp
../../corelib/serialization/qtextstream.cpp
- ../../corelib/serialization/qxmlstream.cpp
- ../../corelib/serialization/qxmlstreamgrammar.cpp
- ../../corelib/serialization/qxmlutils.cpp
../../corelib/text/qbytearray.cpp
../../corelib/text/qbytearraylist.cpp
../../corelib/text/qbytearraymatcher.cpp
+ ../../corelib/text/qlatin1stringmatcher.cpp
../../corelib/text/qlocale.cpp
../../corelib/text/qlocale_tools.cpp
../../corelib/text/qregularexpression.cpp
@@ -83,29 +61,24 @@ qt_internal_extend_target(Bootstrap
../../corelib/time/qcalendar.cpp
../../corelib/time/qdatetime.cpp
../../corelib/time/qgregoriancalendar.cpp
+ ../../corelib/time/qlocaltime.cpp
../../corelib/time/qromancalendar.cpp
+ ../../corelib/time/qtimezone.cpp
../../corelib/tools/qarraydata.cpp
- ../../corelib/tools/qbitarray.cpp
../../corelib/tools/qcommandlineoption.cpp
../../corelib/tools/qcommandlineparser.cpp
../../corelib/tools/qcryptographichash.cpp
../../corelib/tools/qhash.cpp
- ../../corelib/tools/qline.cpp
- ../../corelib/tools/qpoint.cpp
- ../../corelib/tools/qrect.cpp
../../corelib/tools/qringbuffer.cpp
- ../../corelib/tools/qsize.cpp
- ../../corelib/tools/qversionnumber.cpp
- ../../xml/dom/qdom.cpp
DEFINES
HAVE_CONFIG_H
QT_TYPESAFE_FLAGS
- PUBLIC_DEFINES # special case
- QT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} # special case
- QT_VERSION_MINOR=${PROJECT_VERSION_MINOR} # special case
- QT_VERSION_PATCH=${PROJECT_VERSION_PATCH} # special case
- QT_VERSION_STR="${PROJECT_VERSION}" # special case
- QT_USE_QSTRINGBUILDER # special case
+ PUBLIC_DEFINES
+ QT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
+ QT_VERSION_MINOR=${PROJECT_VERSION_MINOR}
+ QT_VERSION_PATCH=${PROJECT_VERSION_PATCH}
+ QT_VERSION_STR="${PROJECT_VERSION}"
+ QT_USE_QSTRINGBUILDER
QT_BOOTSTRAPPED
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
@@ -113,20 +86,14 @@ qt_internal_extend_target(Bootstrap
INCLUDE_DIRECTORIES
..
../../3rdparty/tinycbor/src
- PUBLIC_INCLUDE_DIRECTORIES # special case
- $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES> # special case
- $<TARGET_PROPERTY:Xml,INCLUDE_DIRECTORIES> # special case
- PUBLIC_LIBRARIES # special case
- Qt::Platform # special case
+ PUBLIC_INCLUDE_DIRECTORIES
+ $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES>
+ ../../corelib/global
+ PUBLIC_LIBRARIES
+ Qt::Platform
+ NO_UNITY_BUILD
)
-#### Keys ignored in scope 1:.:.:bootstrap.pro:<TRUE>:
-# INSTALLS = "lib"
-# MODULE_CONFIG = "gc_binaries"
-# MODULE_INCNAME = "QtCore" "QtXml"
-# _OPTION = "host_build"
-# lib.CONFIG = "dummy_install"
-
## Scopes:
#####################################################################
@@ -136,26 +103,24 @@ qt_internal_extend_target(Bootstrap CONDITION UNIX
../../corelib/io/qfilesystemiterator_unix.cpp
../../corelib/io/qfsfileengine_unix.cpp
../../corelib/kernel/qcore_unix.cpp
- ../../corelib/kernel/qsharedmemory_posix.cpp
- ../../corelib/kernel/qsharedmemory_systemv.cpp
- ../../corelib/kernel/qsharedmemory_unix.cpp
- ../../corelib/kernel/qsystemsemaphore_posix.cpp
- ../../corelib/kernel/qsystemsemaphore_systemv.cpp
- ../../corelib/kernel/qsystemsemaphore_unix.cpp
)
+if(APPLE)
+ set_source_files_properties(../../corelib/io/qfilesystemengine_unix.cpp PROPERTIES LANGUAGE OBJCXX)
+ qt_internal_extend_target(Bootstrap CONDITION
+ PUBLIC_LIBRARIES ${FWUniformTypeIdentifiers}
+ )
+endif()
qt_internal_extend_target(Bootstrap CONDITION WIN32
SOURCES
- ../../corelib/global/qoperatingsystemversion_win.cpp
../../corelib/io/qfilesystemengine_win.cpp
../../corelib/io/qfilesystemiterator_win.cpp
../../corelib/io/qfsfileengine_win.cpp
../../corelib/io/qstandardpaths_win.cpp
../../corelib/kernel/qcoreapplication_win.cpp
- ../../corelib/kernel/qsharedmemory_win.cpp
- ../../corelib/kernel/qsystemsemaphore_win.cpp
../../corelib/kernel/qwinregistry.cpp
../../corelib/plugin/qsystemlibrary.cpp
+ ../../corelib/kernel/qfunctions_win.cpp
PUBLIC_LIBRARIES
advapi32
netapi32
@@ -166,10 +131,12 @@ qt_internal_extend_target(Bootstrap CONDITION WIN32
qt_internal_extend_target(Bootstrap CONDITION APPLE
SOURCES
+ ../../corelib/global/qoperatingsystemversion.cpp
../../corelib/global/qoperatingsystemversion_darwin.mm
../../corelib/kernel/qcore_foundation.mm
../../corelib/kernel/qcore_mac.mm
../../corelib/kernel/qcoreapplication_mac.cpp
+ ../../corelib/tools/qversionnumber.cpp
PUBLIC_LIBRARIES
${FWFoundation}
)
@@ -197,6 +164,7 @@ qt_internal_extend_target(Bootstrap CONDITION CMAKE_CROSSCOMPILING OR NOT QT_FEA
../../3rdparty/pcre2/src/pcre2.h
../../3rdparty/pcre2/src/pcre2_auto_possess.c
../../3rdparty/pcre2/src/pcre2_chartables.c
+ ../../3rdparty/pcre2/src/pcre2_chkdint.c
../../3rdparty/pcre2/src/pcre2_compile.c
../../3rdparty/pcre2/src/pcre2_config.c
../../3rdparty/pcre2/src/pcre2_context.c
@@ -229,7 +197,7 @@ qt_internal_extend_target(Bootstrap CONDITION CMAKE_CROSSCOMPILING OR NOT QT_FEA
DEFINES
PCRE2_CODE_UNIT_WIDTH=16
PCRE2_DISABLE_JIT
- PUBLIC_INCLUDE_DIRECTORIES # special case
+ PUBLIC_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/pcre2/src>
)
@@ -248,10 +216,6 @@ qt_internal_extend_target(Bootstrap CONDITION MINGW AND WIN32
uuid
)
-#### Keys ignored in scope 22:.:../../3rdparty/pcre2:../../3rdparty/pcre2/pcre2.pri:QT_FEATURE_intelcet:
-# QMAKE_CFLAGS = "$$QMAKE_CFLAGS_SHSTK"
-
-# special case begin
target_link_libraries(Bootstrap PRIVATE PlatformCommonInternal)
qt_internal_apply_gc_binaries(Bootstrap PUBLIC)
set_target_properties(Bootstrap PROPERTIES AUTOMOC OFF AUTOUIC OFF AUTORCC OFF)
@@ -260,6 +224,9 @@ qt_set_msvc_cplusplus_options(Bootstrap PUBLIC)
qt_set_common_target_properties(Bootstrap)
qt_internal_apply_intel_cet(Bootstrap PUBLIC)
+if(WARNINGS_ARE_ERRORS)
+ qt_internal_set_warnings_are_errors_flags(Bootstrap PRIVATE)
+endif()
qt_internal_extend_target(Bootstrap CONDITION MSVC
DEFINES
_CRT_SECURE_NO_WARNINGS
@@ -269,4 +236,3 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.20.0" AND QT_FEATURE_debug_and_release
set_property(TARGET Bootstrap
PROPERTY EXCLUDE_FROM_ALL "$<NOT:$<CONFIG:${QT_MULTI_CONFIG_FIRST_CONFIG}>>")
endif()
-# special case end
diff --git a/src/tools/cmake_automoc_parser/CMakeLists.txt b/src/tools/cmake_automoc_parser/CMakeLists.txt
index 927d54a2fd..a58c9c9ff1 100644
--- a/src/tools/cmake_automoc_parser/CMakeLists.txt
+++ b/src/tools/cmake_automoc_parser/CMakeLists.txt
@@ -1,12 +1,16 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#####################################################################
## moc Tool:
#####################################################################
qt_get_tool_target_name(target_name cmake_automoc_parser)
qt_internal_add_tool(${target_name}
- BOOTSTRAP
+ CORE_LIBRARY Bootstrap
+ TARGET_DESCRIPTION "Qt CMake AUTOMOC Parser"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
main.cpp
DEFINES
diff --git a/src/tools/cmake_automoc_parser/main.cpp b/src/tools/cmake_automoc_parser/main.cpp
index 70cfcb1b68..de484b184b 100644
--- a/src/tools/cmake_automoc_parser/main.cpp
+++ b/src/tools/cmake_automoc_parser/main.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QtCore/qglobal.h>
@@ -51,6 +26,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
using AutoGenHeaderMap = QMap<QString, QString>;
using AutoGenSourcesList = QList<QString>;
@@ -75,9 +52,9 @@ static bool readAutogenInfoJson(AutoGenHeaderMap &headers, AutoGenSourcesList &s
}
QJsonObject rootObject = doc.object();
- QJsonValue headersValue = rootObject.value(QLatin1String("HEADERS"));
- QJsonValue sourcesValue = rootObject.value(QLatin1String("SOURCES"));
- QJsonValue headerExtValue = rootObject.value(QLatin1String("HEADER_EXTENSIONS"));
+ QJsonValue headersValue = rootObject.value("HEADERS"_L1);
+ QJsonValue sourcesValue = rootObject.value("SOURCES"_L1);
+ QJsonValue headerExtValue = rootObject.value("HEADER_EXTENSIONS"_L1);
if (!headersValue.isArray() || !sourcesValue.isArray() || !headerExtValue.isArray()) {
fprintf(stderr,
@@ -154,20 +131,22 @@ static bool readParseCache(ParseCacheMap &entries, const QString &parseCacheFile
// ....
QTextStream textStream(&file);
- const QString mmcKey = QString(QLatin1String(" mmc:"));
- const QString miuKey = QString(QLatin1String(" miu:"));
- const QString uicKey = QString(QLatin1String(" uic:"));
- const QString midKey = QString(QLatin1String(" mid:"));
- const QString mdpKey = QString(QLatin1String(" mdp:"));
- const QString udpKey = QString(QLatin1String(" udp:"));
+ const QString mmcKey = QString(" mmc:"_L1);
+ const QString miuKey = QString(" miu:"_L1);
+ const QString uicKey = QString(" uic:"_L1);
+ const QString midKey = QString(" mid:"_L1);
+ const QString mdpKey = QString(" mdp:"_L1);
+ const QString udpKey = QString(" udp:"_L1);
QString line;
bool mmc_key_found = false;
while (textStream.readLineInto(&line)) {
- if (!line.startsWith(QLatin1Char(' '))) {
+ if (!line.startsWith(u' ')) {
if (!mocEntries.isEmpty() || mmc_key_found || !mocIncludes.isEmpty()) {
entries.insert(source,
ParseCacheEntry { std::move(mocEntries), std::move(mocIncludes) });
source.clear();
+ mocEntries = {};
+ mocIncludes = {};
mmc_key_found = false;
}
source = line;
@@ -206,17 +185,14 @@ static bool writeJsonFiles(const QList<QString> &fileList, const QString &fileLi
}
qint64 timestamp = std::numeric_limits<qint64>::min();
- QByteArray timestampBuffer = timestampFile.readAll();
- if (timestampBuffer.size() == sizeof(timestamp)) {
- QDataStream istream(&timestampBuffer, QIODevice::ReadOnly);
- istream >> timestamp;
- }
+ if (timestampFile.size() == sizeof(timestamp))
+ timestampFile.read(reinterpret_cast<char *>(&timestamp), sizeof(timestamp));
// Check if any of the metatype json files produced by automoc is newer than the last file
// processed by cmake_automoc parser
for (const auto &jsonFile : fileList) {
const qint64 jsonFileLastModified =
- QFileInfo(jsonFile).lastModified().toMSecsSinceEpoch();
+ QFileInfo(jsonFile).lastModified(QTimeZone::UTC).toMSecsSinceEpoch();
if (jsonFileLastModified > timestamp) {
timestamp = jsonFileLastModified;
}
@@ -236,11 +212,8 @@ static bool writeJsonFiles(const QList<QString> &fileList, const QString &fileLi
textStream.flush();
// Update the timestamp according the newest json file timestamp.
- timestampBuffer.clear();
- QDataStream ostream(&timestampBuffer, QIODevice::WriteOnly);
- ostream << timestamp;
timestampFile.resize(0);
- timestampFile.write(timestampBuffer);
+ timestampFile.write(reinterpret_cast<char *>(&timestamp), sizeof(timestamp));
}
return true;
}
@@ -346,7 +319,7 @@ int main(int argc, char **argv)
const QString base = fileInfo.path() + fileInfo.completeBaseName();
// 1a) erase header
for (const auto &ext : headerExtList) {
- const QString headerPath = base + QLatin1Char('.') + ext;
+ const QString headerPath = base + u'.' + ext;
auto it = autoGenHeaders.find(headerPath);
if (it != autoGenHeaders.end()) {
autoGenHeaders.erase(it);
@@ -354,19 +327,18 @@ int main(int argc, char **argv)
}
}
// Add extra moc files
- for (const auto &mocFile : it.value().mocFiles) {
- jsonFileList.push_back(dir.filePath(mocFile) + QLatin1String(".json"));
- }
+ for (const auto &mocFile : it.value().mocFiles)
+ jsonFileList.push_back(dir.filePath(mocFile) + ".json"_L1);
// Add main moc files
for (const auto &mocFile : it.value().mocIncludes) {
- jsonFileList.push_back(dir.filePath(mocFile) + QLatin1String(".json"));
+ jsonFileList.push_back(dir.filePath(mocFile) + ".json"_L1);
// 1b) Locate this header and delete it
constexpr int mocKeyLen = 4; // length of "moc_"
const QString headerBaseName =
QFileInfo(mocFile.right(mocFile.size() - mocKeyLen)).completeBaseName();
bool breakFree = false;
for (auto &ext : headerExtList) {
- const QString headerSuffix = headerBaseName + QLatin1Char('.') + ext;
+ const QString headerSuffix = headerBaseName + u'.' + ext;
for (auto it = autoGenHeaders.begin(); it != autoGenHeaders.end(); ++it) {
if (it.key().endsWith(headerSuffix)
&& QFileInfo(it.key()).completeBaseName() == headerBaseName) {
@@ -392,8 +364,7 @@ int main(int argc, char **argv)
const QString pathPrefix = !isMultiConfig
? QStringLiteral("../")
: QString();
- const QString jsonPath =
- dir.filePath(pathPrefix + mapIt.value() + QLatin1String(".json"));
+ const QString jsonPath = dir.filePath(pathPrefix + mapIt.value() + ".json"_L1);
jsonFileList.push_back(jsonPath);
}
diff --git a/src/tools/configure.cmake b/src/tools/configure.cmake
index 86b9fa7000..f813b727ba 100644
--- a/src/tools/configure.cmake
+++ b/src/tools/configure.cmake
@@ -1,20 +1,23 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
qt_feature("androiddeployqt" PRIVATE
SECTION "Deployment"
LABEL "Android deployment tool"
PURPOSE "The Android deployment tool automates the process of creating Android packages."
- CONDITION NOT CMAKE_CROSSCOMPILING AND QT_FEATURE_regularexpression)
+ CONDITION NOT CMAKE_CROSSCOMPILING AND QT_FEATURE_regularexpression AND QT_FEATURE_settings)
qt_feature("macdeployqt" PRIVATE
SECTION "Deployment"
LABEL "macOS deployment tool"
PURPOSE "The Mac deployment tool automates the process of creating a deployable application bundle that contains the Qt libraries as private frameworks."
AUTODETECT CMAKE_HOST_APPLE
- CONDITION MACOS)
+ CONDITION MACOS AND QT_FEATURE_thread)
qt_feature("windeployqt" PRIVATE
SECTION "Deployment"
LABEL "Windows deployment tool"
- PURPOSE "The Windows deployment tool is designed to automate the process of creating a deployable folder containing the Qt-related dependencies (libraries, QML imports, plugins, and translations) required to run the application from that folder. It creates a sandbox for Universal Windows Platform (UWP) or an installation tree for Windows desktop applications, which can be easily bundled into an installation package."
+ PURPOSE "The Windows deployment tool is designed to automate the process of creating a deployable folder containing the Qt-related dependencies (libraries, QML imports, plugins, and translations) required to run the application from that folder. The folder can be easily bundled into an installation package."
AUTODETECT CMAKE_HOST_WIN32
CONDITION WIN32)
diff --git a/src/tools/macdeployqt/CMakeLists.txt b/src/tools/macdeployqt/CMakeLists.txt
index cbce4e4ca3..2e01ec90b4 100644
--- a/src/tools/macdeployqt/CMakeLists.txt
+++ b/src/tools/macdeployqt/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from macdeployqt.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_FEATURE_macdeployqt)
return()
diff --git a/src/tools/macdeployqt/macdeployqt/CMakeLists.txt b/src/tools/macdeployqt/macdeployqt/CMakeLists.txt
index 85f117667d..6cd66adaa7 100644
--- a/src/tools/macdeployqt/macdeployqt/CMakeLists.txt
+++ b/src/tools/macdeployqt/macdeployqt/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#####################################################################
## macdeployqt Tool:
#####################################################################
@@ -6,10 +9,13 @@ qt_get_tool_target_name(target_name macdeployqt)
qt_internal_add_tool(${target_name}
TOOLS_TARGET Core
USER_FACING
+ INSTALL_VERSIONED_LINK
TARGET_DESCRIPTION "Qt macOS Deployment Tool"
SOURCES
../shared/shared.cpp
main.cpp
+ DEFINES
+ QT_NO_FOREACH
LIBRARIES
${FWCoreFoundation}
)
diff --git a/src/tools/macdeployqt/macdeployqt/main.cpp b/src/tools/macdeployqt/macdeployqt/main.cpp
index 145ee854af..8b6c476fa5 100644
--- a/src/tools/macdeployqt/macdeployqt/main.cpp
+++ b/src/tools/macdeployqt/macdeployqt/main.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QCoreApplication>
#include <QDir>
#include <QLibraryInfo>
diff --git a/src/tools/macdeployqt/shared/shared.cpp b/src/tools/macdeployqt/shared/shared.cpp
index 584b541c9a..6ff269b36d 100644
--- a/src/tools/macdeployqt/shared/shared.cpp
+++ b/src/tools/macdeployqt/shared/shared.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QCoreApplication>
#include <QString>
#include <QStringList>
@@ -34,6 +9,8 @@
#include <QProcess>
#include <QDir>
#include <QSet>
+#include <QVariant>
+#include <QVariantMap>
#include <QStack>
#include <QDirIterator>
#include <QLibraryInfo>
@@ -62,6 +39,7 @@ bool deployFramework = false;
using std::cout;
using std::endl;
+using namespace Qt::StringLiterals;
bool operator==(const FrameworkInfo &a, const FrameworkInfo &b)
{
@@ -174,7 +152,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath)
LogDebug() << " inspecting" << binaryPath;
QProcess otool;
otool.start("otool", QStringList() << "-L" << binaryPath);
- otool.waitForFinished();
+ otool.waitForFinished(-1);
if (otool.exitStatus() != QProcess::NormalExit || otool.exitCode() != 0) {
LogError() << otool.readAllStandardError();
@@ -183,7 +161,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath)
static const QRegularExpression regexp(QStringLiteral(
"^\\t(.+) \\(compatibility version (\\d+\\.\\d+\\.\\d+), "
- "current version (\\d+\\.\\d+\\.\\d+)(, weak)?\\)$"));
+ "current version (\\d+\\.\\d+\\.\\d+)(, weak|, reexport)?\\)$"));
QString output = otool.readAllStandardOutput();
QStringList outputLines = output.split("\n", Qt::SkipEmptyParts);
@@ -194,7 +172,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath)
outputLines.removeFirst(); // remove line containing the binary path
if (binaryPath.contains(".framework/") || binaryPath.endsWith(".dylib")) {
- const auto match = regexp.match(outputLines.first());
+ const auto match = regexp.match(outputLines.constFirst());
if (match.hasMatch()) {
QString installname = match.captured(1);
if (QFileInfo(binaryPath).fileName() == QFileInfo(installname).fileName()) {
@@ -206,7 +184,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath)
info.installName = binaryPath;
}
} else {
- LogDebug() << "Could not parse otool output line:" << outputLines.first();
+ LogDebug() << "Could not parse otool output line:" << outputLines.constFirst();
outputLines.removeFirst();
}
}
@@ -214,6 +192,8 @@ OtoolInfo findDependencyInfo(const QString &binaryPath)
for (const QString &outputLine : outputLines) {
const auto match = regexp.match(outputLine);
if (match.hasMatch()) {
+ if (match.captured(1) == info.installName)
+ continue; // Another arch reference to the same binary
DylibInfo dylib;
dylib.binaryPath = match.captured(1);
dylib.compatibilityVersion = QVersionNumber::fromString(match.captured(2));
@@ -307,15 +287,15 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl
for (QString &path : librarySearchPath) {
if (!path.endsWith("/"))
path += '/';
- QString nameInPath = path + parts.join(QLatin1Char('/'));
+ QString nameInPath = path + parts.join(u'/');
if (QFile::exists(nameInPath)) {
- info.frameworkDirectory = path + partsCopy.join(QLatin1Char('/'));
+ info.frameworkDirectory = path + partsCopy.join(u'/');
break;
}
}
if (currentPart.contains(".framework")) {
if (info.frameworkDirectory.isEmpty())
- info.frameworkDirectory = "/Library/Frameworks/" + partsCopy.join(QLatin1Char('/'));
+ info.frameworkDirectory = "/Library/Frameworks/" + partsCopy.join(u'/');
if (!info.frameworkDirectory.endsWith("/"))
info.frameworkDirectory += "/";
state = FrameworkName;
@@ -323,7 +303,7 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl
continue;
} else if (currentPart.contains(".dylib")) {
if (info.frameworkDirectory.isEmpty())
- info.frameworkDirectory = "/usr/lib/" + partsCopy.join(QLatin1Char('/'));
+ info.frameworkDirectory = "/usr/lib/" + partsCopy.join(u'/');
if (!info.frameworkDirectory.endsWith("/"))
info.frameworkDirectory += "/";
state = DylibName;
@@ -455,7 +435,7 @@ QStringList findAppLibraries(const QString &appBundlePath)
{
QStringList result;
// dylibs
- QDirIterator iter(appBundlePath, QStringList() << QString::fromLatin1("*.dylib"),
+ QDirIterator iter(appBundlePath, QStringList() << QString::fromLatin1("*.dylib") << QString::fromLatin1("*.so"),
QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories);
while (iter.hasNext()) {
iter.next();
@@ -618,10 +598,14 @@ QStringList getBinaryDependencies(const QString executablePath,
QString binary = QDir::cleanPath(executablePath + trimmedLine.mid(QStringLiteral("@executable_path/").length()));
if (binary != path)
binaries.append(binary);
+ } else if (trimmedLine.startsWith("@loader_path/")) {
+ QString binary = QDir::cleanPath(QFileInfo(path).path() + "/" + trimmedLine.mid(QStringLiteral("@loader_path/").length()));
+ if (binary != path)
+ binaries.append(binary);
} else if (trimmedLine.startsWith("@rpath/")) {
if (!rpathsLoaded) {
rpaths = getBinaryRPaths(path, true, executablePath);
- foreach (const QString &binaryPath, additionalBinariesContainingRpaths)
+ for (const QString &binaryPath : additionalBinariesContainingRpaths)
rpaths += getBinaryRPaths(binaryPath, true);
rpaths.removeDuplicates();
rpathsLoaded = true;
@@ -647,22 +631,27 @@ QStringList getBinaryDependencies(const QString executablePath,
}
// copies everything _inside_ sourcePath to destinationPath
-bool recursiveCopy(const QString &sourcePath, const QString &destinationPath)
+bool recursiveCopy(const QString &sourcePath, const QString &destinationPath,
+ const QRegularExpression &ignoreRegExp = QRegularExpression())
{
- if (!QDir(sourcePath).exists())
+ const QDir sourceDir(sourcePath);
+ if (!sourceDir.exists())
return false;
QDir().mkpath(destinationPath);
LogNormal() << "copy:" << sourcePath << destinationPath;
- QStringList files = QDir(sourcePath).entryList(QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot);
+ const QStringList files = sourceDir.entryList(QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot);
+ const bool hasValidRegExp = ignoreRegExp.isValid() && ignoreRegExp.pattern().length() > 0;
for (const QString &file : files) {
+ if (hasValidRegExp && ignoreRegExp.match(file).hasMatch())
+ continue;
const QString fileSourcePath = sourcePath + "/" + file;
const QString fileDestinationPath = destinationPath + "/" + file;
copyFilePrintStatus(fileSourcePath, fileDestinationPath);
}
- QStringList subdirs = QDir(sourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot);
+ const QStringList subdirs = sourceDir.entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot);
for (const QString &dir : subdirs) {
recursiveCopy(sourcePath + "/" + dir, destinationPath + "/" + dir);
}
@@ -676,9 +665,11 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QList<QString> &
LogNormal() << "copy:" << sourcePath << destinationPath;
const bool isDwarfPath = sourcePath.endsWith("DWARF");
- QStringList files = QDir(sourcePath).entryList(QStringList() << QStringLiteral("*"), QDir::Files | QDir::NoDotAndDotDot);
+ const QDir sourceDir(sourcePath);
+
+ const QStringList files = sourceDir.entryList(QStringList() << QStringLiteral("*"), QDir::Files | QDir::NoDotAndDotDot);
for (const QString &file : files) {
- const QString fileSourcePath = sourcePath + QLatin1Char('/') + file;
+ const QString fileSourcePath = sourcePath + u'/' + file;
if (file.endsWith("_debug.dylib")) {
continue; // Skip debug versions
@@ -699,7 +690,7 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QList<QString> &
QString fileDestinationPath = fileDestinationDir + file;
// The .dylib symlink destination path:
- QString linkDestinationPath = destinationPath + QLatin1Char('/') + file;
+ QString linkDestinationPath = destinationPath + u'/' + file;
// The (relative) link; with a correct number of "../"'s.
QString linkPath = QStringLiteral("PlugIns/quick/") + file;
@@ -717,14 +708,14 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QList<QString> &
deployQtFrameworks(frameworks, appBundlePath, QStringList(fileDestinationPath), useDebugLibs, useLoaderPath);
}
} else {
- QString fileDestinationPath = destinationPath + QLatin1Char('/') + file;
+ QString fileDestinationPath = destinationPath + u'/' + file;
copyFilePrintStatus(fileSourcePath, fileDestinationPath);
}
}
- QStringList subdirs = QDir(sourcePath).entryList(QStringList() << QStringLiteral("*"), QDir::Dirs | QDir::NoDotAndDotDot);
+ const QStringList subdirs = sourceDir.entryList(QStringList() << QStringLiteral("*"), QDir::Dirs | QDir::NoDotAndDotDot);
for (const QString &dir : subdirs) {
- recursiveCopyAndDeploy(appBundlePath, rpaths, sourcePath + QLatin1Char('/') + dir, destinationPath + QLatin1Char('/') + dir);
+ recursiveCopyAndDeploy(appBundlePath, rpaths, sourcePath + u'/' + dir, destinationPath + u'/' + dir);
}
}
@@ -737,8 +728,8 @@ QString copyDylib(const FrameworkInfo &framework, const QString path)
// Construct destination paths. The full path typically looks like
// MyApp.app/Contents/Frameworks/libfoo.dylib
- QString dylibDestinationDirectory = path + QLatin1Char('/') + framework.frameworkDestinationDirectory;
- QString dylibDestinationBinaryPath = dylibDestinationDirectory + QLatin1Char('/') + framework.binaryName;
+ QString dylibDestinationDirectory = path + u'/' + framework.frameworkDestinationDirectory;
+ QString dylibDestinationBinaryPath = dylibDestinationDirectory + u'/' + framework.binaryName;
// Create destination directory
if (!QDir().mkpath(dylibDestinationDirectory)) {
@@ -764,9 +755,9 @@ QString copyFramework(const FrameworkInfo &framework, const QString path)
// Construct destination paths. The full path typically looks like
// MyApp.app/Contents/Frameworks/Foo.framework/Versions/5/QtFoo
- QString frameworkDestinationDirectory = path + QLatin1Char('/') + framework.frameworkDestinationDirectory;
- QString frameworkBinaryDestinationDirectory = frameworkDestinationDirectory + QLatin1Char('/') + framework.binaryDirectory;
- QString frameworkDestinationBinaryPath = frameworkBinaryDestinationDirectory + QLatin1Char('/') + framework.binaryName;
+ QString frameworkDestinationDirectory = path + u'/' + framework.frameworkDestinationDirectory;
+ QString frameworkBinaryDestinationDirectory = frameworkDestinationDirectory + u'/' + framework.binaryDirectory;
+ QString frameworkDestinationBinaryPath = frameworkBinaryDestinationDirectory + u'/' + framework.binaryName;
// Return if the framework has aleardy been deployed
if (QDir(frameworkDestinationDirectory).exists() && !alwaysOwerwriteEnabled)
@@ -788,14 +779,16 @@ QString copyFramework(const FrameworkInfo &framework, const QString path)
// Copy Resources/, Libraries/ and Helpers/
const QString resourcesSourcePath = framework.frameworkPath + "/Resources";
- const QString resourcesDestianationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Resources";
- recursiveCopy(resourcesSourcePath, resourcesDestianationPath);
+ const QString resourcesDestinationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Resources";
+ // Ignore *.prl files that are in the Resources directory
+ recursiveCopy(resourcesSourcePath, resourcesDestinationPath,
+ QRegularExpression("\\A(?:[^/]*\\.prl)\\z"));
const QString librariesSourcePath = framework.frameworkPath + "/Libraries";
- const QString librariesDestianationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Libraries";
- bool createdLibraries = recursiveCopy(librariesSourcePath, librariesDestianationPath);
+ const QString librariesDestinationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Libraries";
+ bool createdLibraries = recursiveCopy(librariesSourcePath, librariesDestinationPath);
const QString helpersSourcePath = framework.frameworkPath + "/Helpers";
- const QString helpersDestianationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Helpers";
- bool createdHelpers = recursiveCopy(helpersSourcePath, helpersDestianationPath);
+ const QString helpersDestinationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Helpers";
+ bool createdHelpers = recursiveCopy(helpersSourcePath, helpersDestinationPath);
// Create symlink structure. Links at the framework root point to Versions/Current/
// which again points to the actual version:
@@ -846,17 +839,23 @@ void changeInstallName(const QString &bundlePath, const FrameworkInfo &framework
for (const QString &binary : binaryPaths) {
QString deployedInstallName;
if (useLoaderPath) {
- deployedInstallName = QLatin1String("@loader_path/")
- + QFileInfo(binary).absoluteDir().relativeFilePath(absBundlePath + QLatin1Char('/') + framework.binaryDestinationDirectory + QLatin1Char('/') + framework.binaryName);
+ deployedInstallName = "@loader_path/"_L1
+ + QFileInfo(binary).absoluteDir().relativeFilePath(absBundlePath + u'/' + framework.binaryDestinationDirectory + u'/' + framework.binaryName);
} else {
deployedInstallName = framework.deployedInstallName;
}
changeInstallName(framework.installName, deployedInstallName, binary);
// Workaround for the case when the library ID name is a symlink, while the dependencies
// specified using the canonical path to the library (QTBUG-56814)
- QString canonicalInstallName = QFileInfo(framework.installName).canonicalFilePath();
+ QFileInfo fileInfo= QFileInfo(framework.installName);
+ QString canonicalInstallName = fileInfo.canonicalFilePath();
if (!canonicalInstallName.isEmpty() && canonicalInstallName != framework.installName) {
changeInstallName(canonicalInstallName, deployedInstallName, binary);
+ // some libraries' inner dependencies (such as ffmpeg, nettle) use symbol link (QTBUG-100093)
+ QString innerDependency = fileInfo.canonicalPath() + "/" + fileInfo.fileName();
+ if (innerDependency != canonicalInstallName && innerDependency != framework.installName) {
+ changeInstallName(innerDependency, deployedInstallName, binary);
+ }
}
}
}
@@ -869,9 +868,9 @@ void addRPath(const QString &rpath, const QString &binaryPath)
void deployRPaths(const QString &bundlePath, const QList<QString> &rpaths, const QString &binaryPath, bool useLoaderPath)
{
const QString absFrameworksPath = QFileInfo(bundlePath).absoluteFilePath()
- + QLatin1String("/Contents/Frameworks");
+ + "/Contents/Frameworks"_L1;
const QString relativeFrameworkPath = QFileInfo(binaryPath).absoluteDir().relativeFilePath(absFrameworksPath);
- const QString loaderPathToFrameworks = QLatin1String("@loader_path/") + relativeFrameworkPath;
+ const QString loaderPathToFrameworks = "@loader_path/"_L1 + relativeFrameworkPath;
bool rpathToFrameworksFound = false;
QStringList args;
QList<QString> binaryRPaths = getBinaryRPaths(binaryPath, false);
@@ -882,7 +881,8 @@ void deployRPaths(const QString &bundlePath, const QList<QString> &rpaths, const
continue;
}
if (rpaths.contains(resolveDyldPrefix(rpath, binaryPath, binaryPath))) {
- args << "-delete_rpath" << rpath;
+ if (!args.contains(rpath))
+ args << "-delete_rpath" << rpath;
}
}
if (!args.length()) {
@@ -941,18 +941,18 @@ void stripAppBinary(const QString &bundlePath)
bool DeploymentInfo::containsModule(const QString &module, const QString &libInFix) const
{
// Check for framework first
- if (deployedFrameworks.contains(QLatin1String("Qt") + module + libInFix +
- QLatin1String(".framework"))) {
+ if (deployedFrameworks.contains("Qt"_L1 + module + libInFix + ".framework"_L1))
return true;
- }
// Check for dylib
- const QRegularExpression dylibRegExp(QLatin1String("libQt[0-9]+") + module +
- libInFix + QLatin1String(".[0-9]+.dylib"));
+ const QRegularExpression dylibRegExp("libQt[0-9]+"_L1
+ + module + libInFix
+ + (isDebug ? "_debug" : "")
+ + ".[0-9]+.dylib"_L1);
return deployedFrameworks.filter(dylibRegExp).size() > 0;
}
/*
- Deploys the the listed frameworks listed into an app bundle.
+ Deploys the listed frameworks into an app bundle.
The frameworks are searched for dependencies, which are also deployed.
(deploying Qt3Support will also deploy QtNetwork and QtSql for example.)
Returns a DeploymentInfo structure containing the Qt path used and a
@@ -1089,13 +1089,13 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
const auto addPlugins = [&pluginSourcePath,&pluginList,useDebugLibs](const QString &subDirectory,
const std::function<bool(QString)> &predicate = std::function<bool(QString)>()) {
- const QStringList libs = QDir(pluginSourcePath + QLatin1Char('/') + subDirectory)
+ const QStringList libs = QDir(pluginSourcePath + u'/' + subDirectory)
.entryList({QStringLiteral("*.dylib")});
for (const QString &lib : libs) {
if (lib.endsWith(QStringLiteral("_debug.dylib")) != useDebugLibs)
continue;
if (!predicate || predicate(lib))
- pluginList.append(subDirectory + QLatin1Char('/') + lib);
+ pluginList.append(subDirectory + u'/' + lib);
}
};
@@ -1117,8 +1117,10 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
const QString libInfix = getLibInfix(deploymentInfo.deployedFrameworks);
// Network
- if (deploymentInfo.containsModule("Network", libInfix))
+ if (deploymentInfo.containsModule("Network", libInfix)) {
addPlugins(QStringLiteral("tls"));
+ addPlugins(QStringLiteral("networkinformation"));
+ }
// All image formats (svg if QtSvg is used)
const bool usesSvg = deploymentInfo.containsModule("Svg", libInfix);
@@ -1169,7 +1171,7 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
}
static const std::map<QString, std::vector<QString>> map {
- {QStringLiteral("Multimedia"), {QStringLiteral("mediaservice"), QStringLiteral("audio")}},
+ {QStringLiteral("Multimedia"), {QStringLiteral("multimedia")}},
{QStringLiteral("3DRender"), {QStringLiteral("sceneparsers"), QStringLiteral("geometryloaders"), QStringLiteral("renderers")}},
{QStringLiteral("3DQuickRender"), {QStringLiteral("renderplugins")}},
{QStringLiteral("Positioning"), {QStringLiteral("position")}},
@@ -1358,10 +1360,10 @@ bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInf
// Create the destination path from the name
// and version (grabbed from the source path)
// ### let qmlimportscanner provide this.
- name.replace(QLatin1Char('.'), QLatin1Char('/'));
+ name.replace(u'.', u'/');
int secondTolast = path.length() - 2;
QString version = path.mid(secondTolast);
- if (version.startsWith(QLatin1Char('.')))
+ if (version.startsWith(u'.'))
name.append(version);
deployQmlImport(appBundlePath, deploymentInfo.rpathsUsed, path, name);
diff --git a/src/tools/macdeployqt/shared/shared.h b/src/tools/macdeployqt/shared/shared.h
index 48ea24b119..33384e868a 100644
--- a/src/tools/macdeployqt/shared/shared.h
+++ b/src/tools/macdeployqt/shared/shared.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef MAC_DEPLOMYMENT_SHARED_H
#define MAC_DEPLOMYMENT_SHARED_H
@@ -62,7 +37,10 @@ public:
bool isDebugLibrary() const
{
- return binaryName.endsWith(QStringLiteral("_debug"));
+ if (isDylib)
+ return binaryName.contains(QStringLiteral("_debug."));
+ else
+ return binaryName.endsWith(QStringLiteral("_debug"));
}
};
diff --git a/src/tools/moc/CMakeLists.txt b/src/tools/moc/CMakeLists.txt
index bb39145b46..b98b7ab4e9 100644
--- a/src/tools/moc/CMakeLists.txt
+++ b/src/tools/moc/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from moc.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## moc Tool:
@@ -6,10 +7,11 @@
qt_get_tool_target_name(target_name moc)
qt_internal_add_tool(${target_name}
- BOOTSTRAP
+ TRY_RUN
+ CORE_LIBRARY Bootstrap
TARGET_DESCRIPTION "Qt Meta Object Compiler"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
cbordevice.h
collectjson.cpp collectjson.h
@@ -19,7 +21,6 @@ qt_internal_add_tool(${target_name}
outputrevision.h
parser.cpp parser.h
preprocessor.cpp preprocessor.h
- # qdatetime_p.h special case remove
symbols.h
token.cpp token.h
utils.h
@@ -28,6 +29,8 @@ qt_internal_add_tool(${target_name}
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_FROM_BYTEARRAY
QT_NO_FOREACH
+ QT_NO_QPAIR
+ QT_USE_NODISCARD_FILE_OPEN
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
../../3rdparty/tinycbor/src
@@ -35,10 +38,6 @@ qt_internal_add_tool(${target_name}
)
qt_internal_return_unless_building_tools()
-#### Keys ignored in scope 1:.:.:moc.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt Meta Object Compiler"
-# _OPTION = "host_build"
-
## Scopes:
#####################################################################
diff --git a/src/tools/moc/cbordevice.h b/src/tools/moc/cbordevice.h
index dbfc537dd2..7668e4c0be 100644
--- a/src/tools/moc/cbordevice.h
+++ b/src/tools/moc/cbordevice.h
@@ -1,34 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** 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) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CBORDEVICE_H
#define CBORDEVICE_H
+#include <QtCore/qtypes.h>
+
#include <memory>
#include <stdio.h>
diff --git a/src/tools/moc/collectjson.cpp b/src/tools/moc/collectjson.cpp
index 6577a3216b..d542e2abc4 100644
--- a/src/tools/moc/collectjson.cpp
+++ b/src/tools/moc/collectjson.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <qfile.h>
#include <qjsonarray.h>
@@ -85,7 +60,7 @@ int collectJson(const QStringList &jsonFiles, const QString &outputFile, bool sk
QStringList jsonFilesSorted = jsonFiles;
jsonFilesSorted.sort();
- for (const QString &jsonFile : qAsConst(jsonFilesSorted)) {
+ for (const QString &jsonFile : std::as_const(jsonFilesSorted)) {
QFile f(jsonFile);
if (!f.open(QIODevice::ReadOnly)) {
fprintf(stderr, "Error opening %s for reading\n", qPrintable(jsonFile));
diff --git a/src/tools/moc/collectjson.h b/src/tools/moc/collectjson.h
index 3a33952a54..b16ae61519 100644
--- a/src/tools/moc/collectjson.h
+++ b/src/tools/moc/collectjson.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef COLLECTJSON_H
#define COLLECTJSON_H
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 3e838818f9..02e9ef178a 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -1,32 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
-** Copyright (C) 2018 Intel Corporation.
-** 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) 2020 The Qt Company Ltd.
+// Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "generator.h"
#include "cbordevice.h"
@@ -48,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
uint nameToBuiltinType(const QByteArray &name)
{
if (name.isEmpty())
@@ -80,11 +57,12 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
return nullptr;
}
- Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ Generator::Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile,
bool requireCompleteTypes)
- : out(outfile),
+ : parser(moc),
+ out(outfile),
cdef(classDef),
metaTypes(metaTypes),
knownQObjectClasses(knownQObjectClasses),
@@ -92,32 +70,53 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
requireCompleteTypes(requireCompleteTypes)
{
if (cdef->superclassList.size())
- purestSuperClass = cdef->superclassList.constFirst().first;
+ purestSuperClass = cdef->superclassList.constFirst().classname;
}
-static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
+static inline qsizetype lengthOfEscapeSequence(const QByteArray &s, qsizetype i)
{
- if (s.at(i) != '\\' || i >= s.length() - 1)
+ if (s.at(i) != '\\' || i >= s.size() - 1)
return 1;
- const int startPos = i;
+ const qsizetype startPos = i;
++i;
char ch = s.at(i);
if (ch == 'x') {
++i;
- while (i < s.length() && is_hex_char(s.at(i)))
+ while (i < s.size() && isHexDigit(s.at(i)))
++i;
- } else if (is_octal_char(ch)) {
+ } else if (isOctalDigit(ch)) {
while (i < startPos + 4
- && i < s.length()
- && is_octal_char(s.at(i))) {
+ && i < s.size()
+ && isOctalDigit(s.at(i))) {
++i;
}
} else { // single character escape sequence
- i = qMin(i + 1, s.length());
+ i = qMin(i + 1, s.size());
}
return i - startPos;
}
+// Prints \a s to \a out, breaking it into lines of at most ColumnWidth. The
+// opening and closing quotes are NOT included (it's up to the caller).
+static void printStringWithIndentation(FILE *out, const QByteArray &s)
+{
+ static constexpr int ColumnWidth = 72;
+ const qsizetype len = s.size();
+ qsizetype idx = 0;
+
+ do {
+ qsizetype spanLen = qMin(ColumnWidth - 2, len - idx);
+ // don't cut escape sequences at the end of a line
+ const qsizetype backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
+ if (backSlashPos >= idx) {
+ const qsizetype escapeLen = lengthOfEscapeSequence(s, backSlashPos);
+ spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, len - idx);
+ }
+ fprintf(out, "\n \"%.*s\"", int(spanLen), s.constData() + idx);
+ idx += spanLen;
+ } while (idx < len);
+}
+
void Generator::strreg(const QByteArray &s)
{
if (!strings.contains(s))
@@ -126,7 +125,7 @@ void Generator::strreg(const QByteArray &s)
int Generator::stridx(const QByteArray &s)
{
- int i = strings.indexOf(s);
+ int i = int(strings.indexOf(s));
Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings");
return i;
}
@@ -137,8 +136,8 @@ int Generator::stridx(const QByteArray &s)
static int aggregateParameterCount(const QList<FunctionDef> &list)
{
int sum = 0;
- for (int i = 0; i < list.count(); ++i)
- sum += list.at(i).arguments.count() + 1; // +1 for return type
+ for (const FunctionDef &def : list)
+ sum += int(def.arguments.size()) + 1; // +1 for return type
return sum;
}
@@ -175,14 +174,14 @@ bool Generator::registerableMetaType(const QByteArray &propertyType)
#undef STREAM_1ARG_TEMPLATE
;
for (const QByteArray &oneArgTemplateType : oneArgTemplates) {
- QByteArray ba = oneArgTemplateType + "<";
+ const QByteArray ba = oneArgTemplateType + "<";
if (propertyType.startsWith(ba) && propertyType.endsWith(">")) {
- const int argumentSize = propertyType.size() - oneArgTemplateType.size() - 1
+ const qsizetype argumentSize = propertyType.size() - ba.size()
// The closing '>'
- 1
// templates inside templates have an extra whitespace char to strip.
- (propertyType.at(propertyType.size() - 2) == ' ' ? 1 : 0 );
- const QByteArray templateArg = propertyType.mid(oneArgTemplateType.size() + 1, argumentSize);
+ const QByteArray templateArg = propertyType.sliced(ba.size(), argumentSize);
return isBuiltinType(templateArg) || registerableMetaType(templateArg);
}
}
@@ -195,12 +194,28 @@ static bool qualifiedNameEquals(const QByteArray &qualifiedName, const QByteArra
{
if (qualifiedName == name)
return true;
- int index = qualifiedName.indexOf("::");
+ const qsizetype index = qualifiedName.indexOf("::");
if (index == -1)
return false;
return qualifiedNameEquals(qualifiedName.mid(index+2), name);
}
+static QByteArray generateQualifiedClassNameIdentifier(const QByteArray &identifier)
+{
+ QByteArray qualifiedClassNameIdentifier = identifier;
+
+ // Remove ':'s in the name, but be sure not to create any illegal
+ // identifiers in the process. (Don't replace with '_', because
+ // that will create problems with things like NS_::_class.)
+ qualifiedClassNameIdentifier.replace("::", "SCOPE");
+
+ // Also, avoid any leading/trailing underscores (we'll concatenate
+ // the generated name with other prefixes/suffixes, and these latter
+ // may already include an underscore, leading to two underscores)
+ qualifiedClassNameIdentifier = "CLASS" + qualifiedClassNameIdentifier + "ENDCLASS";
+ return qualifiedClassNameIdentifier;
+}
+
void Generator::generateCode()
{
bool isQObject = (cdef->classname == "QObject");
@@ -209,8 +224,7 @@ void Generator::generateCode()
// filter out undeclared enumerators and sets
{
QList<EnumDef> enumList;
- for (int i = 0; i < cdef->enumList.count(); ++i) {
- EnumDef def = cdef->enumList.at(i);
+ for (EnumDef def : std::as_const(cdef->enumList)) {
if (cdef->enumDeclarations.contains(def.name)) {
enumList += def;
}
@@ -237,128 +251,58 @@ void Generator::generateCode()
registerPropertyStrings();
registerEnumStrings();
- QByteArray qualifiedClassNameIdentifier = cdef->qualified;
- qualifiedClassNameIdentifier.replace(':', '_');
+ const bool hasStaticMetaCall =
+ (cdef->hasQObject || !cdef->methodList.isEmpty()
+ || !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
+
+ const QByteArray qualifiedClassNameIdentifier = generateQualifiedClassNameIdentifier(cdef->qualified);
+
+ // ensure the qt_meta_stringdata_XXXX_t type is local
+ fprintf(out, "namespace {\n");
//
-// Build stringdata struct
+// Build the strings using QtMocHelpers::StringData
//
- const int constCharArraySizeLimit = 65535;
- fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
- fprintf(out, " const uint offsetsAndSize[%d];\n", int(strings.size()*2));
- {
- int stringDataLength = 0;
- int stringDataCounter = 0;
- for (int i = 0; i < strings.size(); ++i) {
- int thisLength = strings.at(i).length() + 1;
- stringDataLength += thisLength;
- if (stringDataLength / constCharArraySizeLimit) {
- // save previous stringdata and start computing the next one.
- fprintf(out, " char stringdata%d[%d];\n", stringDataCounter++, stringDataLength - thisLength);
- stringDataLength = thisLength;
- }
- }
- fprintf(out, " char stringdata%d[%d];\n", stringDataCounter, stringDataLength);
-
- }
- fprintf(out, "};\n");
-
- // Macro that expands into a QByteArrayData. The offset member is
- // calculated from 1) the offset of the actual characters in the
- // stringdata.stringdata member, and 2) the stringdata.data index of the
- // QByteArrayData being defined. This calculation relies on the
- // QByteArrayData::data() implementation returning simply "this + offset".
- fprintf(out, "#define QT_MOC_LITERAL(ofs, len) \\\n"
- " uint(offsetof(qt_meta_stringdata_%s_t, stringdata0) + ofs), len \n",
- qualifiedClassNameIdentifier.constData());
- fprintf(out, "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n",
+ fprintf(out, "\n#ifdef QT_MOC_HAS_STRINGDATA\n"
+ "struct qt_meta_stringdata_%s_t {};\n"
+ "constexpr auto qt_meta_stringdata_%s = QtMocHelpers::stringData(",
qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
- fprintf(out, " {\n");
{
- int idx = 0;
- for (int i = 0; i < strings.size(); ++i) {
- const QByteArray &str = strings.at(i);
- fprintf(out, "QT_MOC_LITERAL(%d, %d)", idx, int(str.length()));
- if (i != strings.size() - 1)
- fputc(',', out);
- const QByteArray comment = str.length() > 32 ? str.left(29) + "..." : str;
- fprintf(out, " // \"%s\"\n", comment.size() ? comment.constData() : "");
- idx += str.length() + 1;
- for (int j = 0; j < str.length(); ++j) {
- if (str.at(j) == '\\') {
- int cnt = lengthOfEscapeSequence(str, j) - 1;
- idx -= cnt;
- j += cnt;
- }
- }
- }
- fprintf(out, "\n },\n");
- }
-
-//
-// Build stringdata array
-//
- fprintf(out, " \"");
- int col = 0;
- int len = 0;
- int stringDataLength = 0;
- for (int i = 0; i < strings.size(); ++i) {
- QByteArray s = strings.at(i);
- len = s.length();
- stringDataLength += len + 1;
- if (stringDataLength >= constCharArraySizeLimit) {
- fprintf(out, "\",\n \"");
- stringDataLength = len + 1;
- col = 0;
- } else if (i)
- fputs("\\0", out); // add \0 at the end of each string
-
- if (col && col + len >= 72) {
- fprintf(out, "\"\n \"");
- col = 0;
- } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
- fprintf(out, "\"\"");
- len += 2;
- }
- int idx = 0;
- while (idx < s.length()) {
- if (idx > 0) {
- col = 0;
- fprintf(out, "\"\n \"");
- }
- int spanLen = qMin(70, s.length() - idx);
- // don't cut escape sequences at the end of a line
- int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
- if (backSlashPos >= idx) {
- int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
- spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
- }
- fprintf(out, "%.*s", spanLen, s.constData() + idx);
- idx += spanLen;
- col += spanLen;
+ char comma = 0;
+ for (const QByteArray &str : strings) {
+ if (comma)
+ fputc(comma, out);
+ printStringWithIndentation(out, str);
+ comma = ',';
}
- col += len + 2;
}
-
-// Terminate stringdata struct
- fprintf(out, "\"\n};\n");
- fprintf(out, "#undef QT_MOC_LITERAL\n\n");
+ fprintf(out, "\n);\n"
+ "#else // !QT_MOC_HAS_STRINGDATA\n");
+ fprintf(out, "#error \"qtmochelpers.h not found or too old.\"\n");
+ fprintf(out, "#endif // !QT_MOC_HAS_STRINGDATA\n");
+ fprintf(out, "} // unnamed namespace\n\n");
//
// build the data array
//
int index = MetaObjectPrivateFieldCount;
- fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
+ fprintf(out, "Q_CONSTINIT static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
fprintf(out, "\n // content:\n");
fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision));
fprintf(out, " %4d, // classname\n", stridx(cdef->qualified));
- fprintf(out, " %4d, %4d, // classinfo\n", int(cdef->classInfoList.count()), int(cdef->classInfoList.count() ? index : 0));
- index += cdef->classInfoList.count() * 2;
+ fprintf(out, " %4d, %4d, // classinfo\n", int(cdef->classInfoList.size()), int(cdef->classInfoList.size() ? index : 0));
+ index += cdef->classInfoList.size() * 2;
+
+ qsizetype methodCount = 0;
+ if (qAddOverflow(cdef->signalList.size(), cdef->slotList.size(), &methodCount)
+ || qAddOverflow(cdef->methodList.size(), methodCount, &methodCount)) {
+ parser->error("internal limit exceeded: the total number of member functions"
+ " (including signals and slots) is too big.");
+ }
- int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
- fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
+ fprintf(out, " %4" PRIdQSIZETYPE ", %4d, // methods\n", methodCount, methodCount ? index : 0);
index += methodCount * QMetaObjectPrivate::IntsPerMethod;
if (cdef->revisionedMethods)
index += methodCount;
@@ -369,16 +313,17 @@ void Generator::generateCode()
+ aggregateParameterCount(cdef->constructorList);
index += totalParameterCount * 2 // types and parameter names
- methodCount // return "parameters" don't have names
- - cdef->constructorList.count(); // "this" parameters don't have names
+ - int(cdef->constructorList.size()); // "this" parameters don't have names
- fprintf(out, " %4d, %4d, // properties\n", int(cdef->propertyList.count()), int(cdef->propertyList.count() ? index : 0));
- index += cdef->propertyList.count() * QMetaObjectPrivate::IntsPerProperty;
- fprintf(out, " %4d, %4d, // enums/sets\n", int(cdef->enumList.count()), cdef->enumList.count() ? index : 0);
+ fprintf(out, " %4d, %4d, // properties\n", int(cdef->propertyList.size()), int(cdef->propertyList.size() ? index : 0));
+ index += cdef->propertyList.size() * QMetaObjectPrivate::IntsPerProperty;
+ fprintf(out, " %4d, %4d, // enums/sets\n", int(cdef->enumList.size()), cdef->enumList.size() ? index : 0);
int enumsIndex = index;
- for (int i = 0; i < cdef->enumList.count(); ++i)
- index += 5 + (cdef->enumList.at(i).values.count() * 2);
- fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? int(cdef->constructorList.count()) : 0,
+ for (const EnumDef &def : std::as_const(cdef->enumList))
+ index += QMetaObjectPrivate::IntsPerEnum + (def.values.size() * 2);
+
+ fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? int(cdef->constructorList.size()) : 0,
isConstructible ? index : 0);
int flags = 0;
@@ -388,7 +333,7 @@ void Generator::generateCode()
flags |= PropertyAccessInStaticMetaCall;
}
fprintf(out, " %4d, // flags\n", flags);
- fprintf(out, " %4d, // signalCount\n", int(cdef->signalList.count()));
+ fprintf(out, " %4d, // signalCount\n", int(cdef->signalList.size()));
//
@@ -396,8 +341,14 @@ void Generator::generateCode()
//
generateClassInfos();
- // all property metatypes, + 1 for the type of the current class itself
- int initialMetaTypeOffset = cdef->propertyList.count() + 1;
+ qsizetype propEnumCount = 0;
+ // all property metatypes + all enum metatypes + 1 for the type of the current class itself
+ if (qAddOverflow(cdef->propertyList.size(), cdef->enumList.size(), &propEnumCount)
+ || qAddOverflow(propEnumCount, qsizetype(1), &propEnumCount)
+ || propEnumCount >= std::numeric_limits<int>::max()) {
+ parser->error("internal limit exceeded: number of property and enum metatypes is too big.");
+ }
+ int initialMetaTypeOffset = int(propEnumCount);
//
// Build signals array first, otherwise the signal indices would be wrong
@@ -454,30 +405,20 @@ void Generator::generateCode()
fprintf(out, "\n 0 // eod\n};\n\n");
//
-// Generate internal qt_static_metacall() function
-//
- const bool hasStaticMetaCall =
- (cdef->hasQObject || !cdef->methodList.isEmpty()
- || !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty());
- if (hasStaticMetaCall)
- generateStaticMetacall();
-
-//
// Build extra array
//
QList<QByteArray> extraList;
QMultiHash<QByteArray, QByteArray> knownExtraMetaObject(knownGadgets);
knownExtraMetaObject.unite(knownQObjectClasses);
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
if (isBuiltinType(p.type))
continue;
if (p.type.contains('*') || p.type.contains('<') || p.type.contains('>'))
continue;
- int s = p.type.lastIndexOf("::");
+ const qsizetype s = p.type.lastIndexOf("::");
if (s <= 0)
continue;
@@ -488,7 +429,7 @@ void Generator::generateCode()
QByteArray thisScope = cdef->qualified;
do {
- int s = thisScope.lastIndexOf("::");
+ const qsizetype s = thisScope.lastIndexOf("::");
thisScope = thisScope.left(s);
QByteArray currentScope = thisScope.isEmpty() ? unqualifiedScope : thisScope + "::" + unqualifiedScope;
scopeIt = knownExtraMetaObject.constFind(currentScope);
@@ -514,7 +455,7 @@ void Generator::generateCode()
for (auto it = cdef->enumDeclarations.keyBegin(),
end = cdef->enumDeclarations.keyEnd(); it != end; ++it) {
const QByteArray &enumKey = *it;
- int s = enumKey.lastIndexOf("::");
+ const qsizetype s = enumKey.lastIndexOf("::");
if (s > 0) {
QByteArray scope = enumKey.left(s);
if (scope != "Qt" && !qualifiedNameEquals(cdef->qualified, scope) && !extraList.contains(scope))
@@ -527,28 +468,29 @@ void Generator::generateCode()
//
if (!extraList.isEmpty()) {
- fprintf(out, "static const QMetaObject::SuperData qt_meta_extradata_%s[] = {\n",
+ fprintf(out, "Q_CONSTINIT static const QMetaObject::SuperData qt_meta_extradata_%s[] = {\n",
qualifiedClassNameIdentifier.constData());
- for (int i = 0; i < extraList.count(); ++i) {
- fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", extraList.at(i).constData());
- }
+ for (const QByteArray &ba : std::as_const(extraList))
+ fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", ba.constData());
+
fprintf(out, " nullptr\n};\n\n");
}
//
// Finally create and initialize the static meta object
//
- fprintf(out, "const QMetaObject %s::staticMetaObject = { {\n", cdef->qualified.constData());
+ fprintf(out, "Q_CONSTINIT const QMetaObject %s::staticMetaObject = { {\n",
+ cdef->qualified.constData());
if (isQObject)
fprintf(out, " nullptr,\n");
else if (cdef->superclassList.size() && !cdef->hasQGadget && !cdef->hasQNamespace) // for qobject, we know the super class must have a static metaobject
fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", purestSuperClass.constData());
else if (cdef->superclassList.size()) // for gadgets we need to query at compile time for it
- fprintf(out, " QtPrivate::MetaObjectForType<%s>::value(),\n", purestSuperClass.constData());
+ fprintf(out, " QtPrivate::MetaObjectForType<%s>::value,\n", purestSuperClass.constData());
else
fprintf(out, " nullptr,\n");
- fprintf(out, " qt_meta_stringdata_%s.offsetsAndSize,\n"
+ fprintf(out, " qt_meta_stringdata_%s.offsetsAndSizes,\n"
" qt_meta_data_%s,\n", qualifiedClassNameIdentifier.constData(),
qualifiedClassNameIdentifier.constData());
if (hasStaticMetaCall)
@@ -561,63 +503,75 @@ void Generator::generateCode()
else
fprintf(out, " qt_meta_extradata_%s,\n", qualifiedClassNameIdentifier.constData());
- bool needsComma = false;
+ const char *comma = "";
const bool requireCompleteness = requireCompleteTypes || cdef->requireCompleteMethodTypes;
+ auto stringForType = [requireCompleteness](const QByteArray &type, bool forceComplete) -> QByteArray {
+ const char *forceCompleteType = forceComplete ? ", std::true_type>" : ", std::false_type>";
+ if (requireCompleteness)
+ return type;
+ return "QtPrivate::TypeAndForceComplete<" % type % forceCompleteType;
+ };
if (!requireCompleteness) {
- fprintf(out, "qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t\n", qualifiedClassNameIdentifier.constData());
- needsComma = true;
+ fprintf(out, " qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t", qualifiedClassNameIdentifier.constData());
+ comma = ",";
} else {
- fprintf(out, "qt_metaTypeArray<\n");
+ fprintf(out, " qt_metaTypeArray<");
}
// metatypes for properties
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
- if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data());
- else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", p.type.data());
- needsComma = true;
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
+ fprintf(out, "%s\n // property '%s'\n %s",
+ comma, p.name.constData(), stringForType(p.type, true).constData());
+ comma = ",";
}
+
+ // metatypes for enums
+ for (const EnumDef &e : std::as_const(cdef->enumList)) {
+ fprintf(out, "%s\n // enum '%s'\n %s",
+ comma, e.name.constData(), stringForType(e.qualifiedType(cdef), true).constData());
+ comma = ",";
+ }
+
// type name for the Q_OJBECT/GADGET itself, void for namespaces
auto ownType = !cdef->hasQNamespace ? cdef->classname.data() : "void";
- if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", ownType);
- else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", ownType);
+ fprintf(out, "%s\n // Q_OBJECT / Q_GADGET\n %s",
+ comma, stringForType(ownType, true).constData());
+ comma = ",";
// metatypes for all exposed methods
- // no need to check for needsComma any longer, as we always need one due to the classname being present
- for (const QList<FunctionDef> &methodContainer :
- { cdef->signalList, cdef->slotList, cdef->methodList }) {
- for (int i = 0; i< methodContainer.count(); ++i) {
- const FunctionDef& fdef = methodContainer.at(i);
- if (requireCompleteness)
- fprintf(out, ", %s", fdef.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", fdef.type.name.data());
- for (const auto &argument: fdef.arguments) {
- if (requireCompleteness)
- fprintf(out, ", %s", argument.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
- }
+ // because we definitely printed something above, this section doesn't need comma control
+ const auto allMethods = {&cdef->signalList, &cdef->slotList, &cdef->methodList};
+ for (const QList<FunctionDef> *methodContainer : allMethods) {
+ for (const FunctionDef &fdef : *methodContainer) {
+ fprintf(out, ",\n // method '%s'\n %s",
+ fdef.name.constData(), stringForType(fdef.type.name, false).constData());
+ for (const auto &argument: fdef.arguments)
+ fprintf(out, ",\n %s", stringForType(argument.type.name, false).constData());
}
- fprintf(out, "\n");
}
- for (int i = 0; i< cdef->constructorList.count(); ++i) {
- const FunctionDef& fdef = cdef->constructorList.at(i);
+
+ // but constructors have no return types, so this needs comma control again
+ for (const FunctionDef &fdef : std::as_const(cdef->constructorList)) {
+ if (fdef.arguments.isEmpty())
+ continue;
+
+ fprintf(out, "%s\n // constructor '%s'", comma, fdef.name.constData());
+ comma = "";
for (const auto &argument: fdef.arguments) {
- if (requireCompleteness)
- fprintf(out, ", %s", argument.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
+ fprintf(out, "%s\n %s", comma,
+ stringForType(argument.type.name, false).constData());
+ comma = ",";
}
}
- fprintf(out, "\n");
- fprintf(out, ">,\n");
+ fprintf(out, "\n >,\n");
fprintf(out, " nullptr\n} };\n\n");
+//
+// Generate internal qt_static_metacall() function
+//
+ if (hasStaticMetaCall)
+ generateStaticMetacall();
+
if (!cdef->hasQObject)
return;
@@ -633,18 +587,24 @@ void Generator::generateCode()
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata0))\n"
" return static_cast<void*>(this);\n",
qualifiedClassNameIdentifier.constData());
- for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
- if (cdef->superclassList.at(i).second == FunctionDef::Private)
- continue;
- const char *cname = cdef->superclassList.at(i).first.constData();
- fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(this);\n",
- cname, cname);
+
+ // for all superclasses but the first one
+ if (cdef->superclassList.size() > 1) {
+ auto it = cdef->superclassList.cbegin() + 1;
+ const auto end = cdef->superclassList.cend();
+ for (; it != end; ++it) {
+ if (it->access == FunctionDef::Private)
+ continue;
+ const char *cname = it->classname.constData();
+ fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(this);\n",
+ cname, cname);
+ }
}
- for (int i = 0; i < cdef->interfaceList.size(); ++i) {
- const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i);
- for (int j = 0; j < iface.size(); ++j) {
+
+ for (const QList<ClassDef::Interface> &iface : std::as_const(cdef->interfaceList)) {
+ for (qsizetype j = 0; j < iface.size(); ++j) {
fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData());
- for (int k = j; k >= 0; --k)
+ for (qsizetype k = j; k >= 0; --k)
fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData());
fprintf(out, "this%s;\n", QByteArray(j + 1, ')').constData());
}
@@ -665,8 +625,8 @@ void Generator::generateCode()
//
// Generate internal signal functions
//
- for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
- generateSignal(&cdef->signalList[signalindex], signalindex);
+ for (int signalindex = 0; signalindex < int(cdef->signalList.size()); ++signalindex)
+ generateSignal(&cdef->signalList.at(signalindex), signalindex);
//
// Generate plugin meta data
@@ -677,12 +637,29 @@ void Generator::generateCode()
// Generate function to make sure the non-class signals exist in the parent classes
//
if (!cdef->nonClassSignalList.isEmpty()) {
- fprintf(out, "// If you get a compile error in this function it can be because either\n");
- fprintf(out, "// a) You are using a NOTIFY signal that does not exist. Fix it.\n");
- fprintf(out, "// b) You are using a NOTIFY signal that does exist (in a parent class) but has a non-empty parameter list. This is a moc limitation.\n");
- fprintf(out, "[[maybe_unused]] static void checkNotifySignalValidity_%s(%s *t) {\n", qualifiedClassNameIdentifier.constData(), cdef->qualified.constData());
- for (const QByteArray &nonClassSignal : qAsConst(cdef->nonClassSignalList))
- fprintf(out, " t->%s();\n", nonClassSignal.constData());
+ fprintf(out, "namespace CheckNotifySignalValidity_%s {\n", qualifiedClassNameIdentifier.constData());
+ for (const QByteArray &nonClassSignal : std::as_const(cdef->nonClassSignalList)) {
+ const auto propertyIt = std::find_if(cdef->propertyList.constBegin(),
+ cdef->propertyList.constEnd(),
+ [&nonClassSignal](const PropertyDef &p) {
+ return nonClassSignal == p.notify;
+ });
+ // must find something, otherwise checkProperties wouldn't have inserted an entry into nonClassSignalList
+ Q_ASSERT(propertyIt != cdef->propertyList.constEnd());
+ fprintf(out, "template<typename T> using has_nullary_%s = decltype(std::declval<T>().%s());\n",
+ nonClassSignal.constData(),
+ nonClassSignal.constData());
+ const auto &propertyType = propertyIt->type;
+ fprintf(out, "template<typename T> using has_unary_%s = decltype(std::declval<T>().%s(std::declval<%s>()));\n",
+ nonClassSignal.constData(),
+ nonClassSignal.constData(),
+ propertyType.constData());
+ fprintf(out, "static_assert(qxp::is_detected_v<has_nullary_%s, %s> || qxp::is_detected_v<has_unary_%s, %s>,\n"
+ " \"NOTIFY signal %s does not exist in class (or is private in its parent)\");\n",
+ nonClassSignal.constData(), cdef->qualified.constData(),
+ nonClassSignal.constData(), cdef->qualified.constData(),
+ nonClassSignal.constData());
+ }
fprintf(out, "}\n");
}
}
@@ -690,8 +667,7 @@ void Generator::generateCode()
void Generator::registerClassInfoStrings()
{
- for (int i = 0; i < cdef->classInfoList.size(); ++i) {
- const ClassInfoDef &c = cdef->classInfoList.at(i);
+ for (const ClassInfoDef &c : std::as_const(cdef->classInfoList)) {
strreg(c.name);
strreg(c.value);
}
@@ -704,25 +680,19 @@ void Generator::generateClassInfos()
fprintf(out, "\n // classinfo: key, value\n");
- for (int i = 0; i < cdef->classInfoList.size(); ++i) {
- const ClassInfoDef &c = cdef->classInfoList.at(i);
+ for (const ClassInfoDef &c : std::as_const(cdef->classInfoList))
fprintf(out, " %4d, %4d,\n", stridx(c.name), stridx(c.value));
- }
}
void Generator::registerFunctionStrings(const QList<FunctionDef> &list)
{
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
-
+ for (const FunctionDef &f : list) {
strreg(f.name);
if (!isBuiltinType(f.normalizedType))
strreg(f.normalizedType);
strreg(f.tag);
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
+ for (const ArgumentDef &a : f.arguments) {
if (!isBuiltinType(a.normalizedType))
strreg(a.normalizedType);
strreg(a.name);
@@ -743,9 +713,7 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
return;
fprintf(out, "\n // %ss: name, argc, parameters, tag, flags, initial metatype offsets\n", functype);
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
-
+ for (const FunctionDef &f : list) {
QByteArray comment;
uint flags = type;
if (f.access == FunctionDef::Private) {
@@ -780,7 +748,7 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
comment.append(" | MethodIsConst ");
}
- int argc = f.arguments.count();
+ const int argc = int(f.arguments.size());
fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x, %4d /* %s */,\n",
stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, initialMetatypeOffset, comment.constData());
@@ -792,12 +760,10 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
void Generator::generateFunctionRevisions(const QList<FunctionDef> &list, const char *functype)
{
- if (list.count())
+ if (list.size())
fprintf(out, "\n // %ss: revision\n", functype);
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
+ for (const FunctionDef &f : list)
fprintf(out, " %4d,\n", f.revision);
- }
}
void Generator::generateFunctionParameters(const QList<FunctionDef> &list, const char *functype)
@@ -805,25 +771,22 @@ void Generator::generateFunctionParameters(const QList<FunctionDef> &list, const
if (list.isEmpty())
return;
fprintf(out, "\n // %ss: parameters\n", functype);
- for (int i = 0; i < list.count(); ++i) {
- const FunctionDef &f = list.at(i);
+ for (const FunctionDef &f : list) {
fprintf(out, " ");
// Types
- int argsCount = f.arguments.count();
- for (int j = -1; j < argsCount; ++j) {
- if (j > -1)
- fputc(' ', out);
- const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
- generateTypeInfo(typeName, /*allowEmptyName=*/f.isConstructor);
+ const bool allowEmptyName = f.isConstructor;
+ generateTypeInfo(f.normalizedType, allowEmptyName);
+ fputc(',', out);
+ for (const ArgumentDef &arg : f.arguments) {
+ fputc(' ', out);
+ generateTypeInfo(arg.normalizedType, allowEmptyName);
fputc(',', out);
}
// Parameter names
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &arg = f.arguments.at(j);
+ for (const ArgumentDef &arg : f.arguments)
fprintf(out, " %4d,", stridx(arg.name));
- }
fprintf(out, "\n");
}
@@ -856,8 +819,7 @@ void Generator::generateTypeInfo(const QByteArray &typeName, bool allowEmptyName
void Generator::registerPropertyStrings()
{
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
strreg(p.name);
if (!isBuiltinType(p.type))
strreg(p.type);
@@ -870,10 +832,9 @@ void Generator::generateProperties()
// Create meta data
//
- if (cdef->propertyList.count())
+ if (cdef->propertyList.size())
fprintf(out, "\n // properties: name, type, flags\n");
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
uint flags = Invalid;
if (!isBuiltinType(p.type))
flags |= EnumOrFlag;
@@ -917,7 +878,7 @@ void Generator::generateProperties()
int notifyId = p.notifyId;
if (p.notifyId < -1) {
// signal is in parent class
- const int indexInStrings = strings.indexOf(p.notify);
+ const int indexInStrings = int(strings.indexOf(p.notify));
notifyId = indexInStrings | IsUnresolvedSignal;
}
fprintf(out, ", 0x%.8x, uint(%d), %d,\n", flags, notifyId, p.revision);
@@ -926,13 +887,12 @@ void Generator::generateProperties()
void Generator::registerEnumStrings()
{
- for (int i = 0; i < cdef->enumList.count(); ++i) {
- const EnumDef &e = cdef->enumList.at(i);
+ for (const EnumDef &e : std::as_const(cdef->enumList)) {
strreg(e.name);
if (!e.enumName.isNull())
strreg(e.enumName);
- for (int j = 0; j < e.values.count(); ++j)
- strreg(e.values.at(j));
+ for (const QByteArray &val : e.values)
+ strreg(val);
}
}
@@ -942,9 +902,9 @@ void Generator::generateEnums(int index)
return;
fprintf(out, "\n // enums: name, alias, flags, count, data\n");
- index += 5 * cdef->enumList.count();
+ index += QMetaObjectPrivate::IntsPerEnum * cdef->enumList.size();
int i;
- for (i = 0; i < cdef->enumList.count(); ++i) {
+ for (i = 0; i < cdef->enumList.size(); ++i) {
const EnumDef &e = cdef->enumList.at(i);
int flags = 0;
if (cdef->enumDeclarations.value(e.name))
@@ -955,16 +915,14 @@ void Generator::generateEnums(int index)
stridx(e.name),
e.enumName.isNull() ? stridx(e.name) : stridx(e.enumName),
flags,
- int(e.values.count()),
+ int(e.values.size()),
index);
- index += e.values.count() * 2;
+ index += e.values.size() * 2;
}
fprintf(out, "\n // enum data: key, value\n");
- for (i = 0; i < cdef->enumList.count(); ++i) {
- const EnumDef &e = cdef->enumList.at(i);
- for (int j = 0; j < e.values.count(); ++j) {
- const QByteArray &val = e.values.at(j);
+ for (const EnumDef &e : std::as_const(cdef->enumList)) {
+ for (const QByteArray &val : e.values) {
QByteArray code = cdef->qualified.constData();
if (e.isEnumClass)
code += "::" + (e.enumName.isNull() ? e.name : e.enumName);
@@ -1022,8 +980,6 @@ void Generator::generateMetacall()
}
if (cdef->propertyList.size()) {
-
- fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
if (needElse)
fprintf(out, "else ");
fprintf(out,
@@ -1031,8 +987,7 @@ void Generator::generateMetacall()
" || _c == QMetaObject::ResetProperty || _c == QMetaObject::BindableProperty\n"
" || _c == QMetaObject::RegisterPropertyMetaType) {\n"
" qt_static_metacall(this, _c, _id, _a);\n"
- " _id -= %d;\n }", int(cdef->propertyList.count()));
- fprintf(out, "\n#endif // QT_NO_PROPERTIES");
+ " _id -= %d;\n }", int(cdef->propertyList.size()));
}
if (methodList.size() || cdef->propertyList.size())
fprintf(out, "\n ");
@@ -1040,10 +995,11 @@ void Generator::generateMetacall()
}
+// ### Qt 7 (6.x?): remove
QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper()
{
QMultiMap<QByteArray, int> automaticPropertyMetaTypes;
- for (int i = 0; i < cdef->propertyList.size(); ++i) {
+ for (int i = 0; i < int(cdef->propertyList.size()); ++i) {
const QByteArray propertyType = cdef->propertyList.at(i).type;
if (registerableMetaType(propertyType) && !isBuiltinType(propertyType))
automaticPropertyMetaTypes.insert(propertyType, i);
@@ -1057,7 +1013,7 @@ Generator::methodsWithAutomaticTypesHelper(const QList<FunctionDef> &methodList)
QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypes;
for (int i = 0; i < methodList.size(); ++i) {
const FunctionDef &f = methodList.at(i);
- for (int j = 0; j < f.arguments.count(); ++j) {
+ for (int j = 0; j < f.arguments.size(); ++j) {
const QByteArray argType = f.arguments.at(j).normalizedType;
if (registerableMetaType(argType) && !isBuiltinType(argType))
methodsWithAutomaticTypes[i].insert(argType, j);
@@ -1074,33 +1030,46 @@ void Generator::generateStaticMetacall()
bool needElse = false;
bool isUsed_a = false;
+ const auto generateCtorArguments = [&](int ctorindex) {
+ const FunctionDef &f = cdef->constructorList.at(ctorindex);
+ Q_ASSERT(!f.isPrivateSignal); // That would be a strange ctor indeed
+ int offset = 1;
+
+ const auto begin = f.arguments.cbegin();
+ const auto end = f.arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
+ fprintf(out, ",");
+ fprintf(out, "(*reinterpret_cast<%s>(_a[%d]))",
+ a.typeNameForCast.constData(), offset++);
+ }
+ };
+
if (!cdef->constructorList.isEmpty()) {
fprintf(out, " if (_c == QMetaObject::CreateInstance) {\n");
fprintf(out, " switch (_id) {\n");
- for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) {
+ const int ctorend = int(cdef->constructorList.size());
+ for (int ctorindex = 0; ctorindex < ctorend; ++ctorindex) {
fprintf(out, " case %d: { %s *_r = new %s(", ctorindex,
cdef->classname.constData(), cdef->classname.constData());
- const FunctionDef &f = cdef->constructorList.at(ctorindex);
- int offset = 1;
-
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
- if (j)
- fprintf(out, ",");
- fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++);
- }
- if (f.isPrivateSignal) {
- if (argsCount > 0)
- fprintf(out, ", ");
- fprintf(out, "%s", QByteArray("QPrivateSignal()").constData());
- }
+ generateCtorArguments(ctorindex);
fprintf(out, ");\n");
fprintf(out, " if (_a[0]) *reinterpret_cast<%s**>(_a[0]) = _r; } break;\n",
(cdef->hasQGadget || cdef->hasQNamespace) ? "void" : "QObject");
}
fprintf(out, " default: break;\n");
fprintf(out, " }\n");
+ fprintf(out, " } else if (_c == QMetaObject::ConstructInPlace) {\n");
+ fprintf(out, " switch (_id) {\n");
+ for (int ctorindex = 0; ctorindex < ctorend; ++ctorindex) {
+ fprintf(out, " case %d: { new (_a[0]) %s(",
+ ctorindex, cdef->classname.constData());
+ generateCtorArguments(ctorindex);
+ fprintf(out, "); } break;\n");
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
fprintf(out, " }");
needElse = true;
isUsed_a = true;
@@ -1142,16 +1111,17 @@ void Generator::generateStaticMetacall()
if (f.isRawSlot) {
fprintf(out, "QMethodRawArguments{ _a }");
} else {
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
- if (j)
+ const auto begin = f.arguments.cbegin();
+ const auto end = f.arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
fprintf(out, ",");
fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++);
isUsed_a = true;
}
if (f.isPrivateSignal) {
- if (argsCount > 0)
+ if (!f.arguments.isEmpty())
fprintf(out, ", ");
fprintf(out, "%s", "QPrivateSignal()");
}
@@ -1204,7 +1174,7 @@ void Generator::generateStaticMetacall()
fprintf(out, " else if (_c == QMetaObject::IndexOfMethod) {\n");
fprintf(out, " int *result = reinterpret_cast<int *>(_a[0]);\n");
bool anythingUsed = false;
- for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) {
+ for (int methodindex = 0; methodindex < int(cdef->signalList.size()); ++methodindex) {
const FunctionDef &f = cdef->signalList.at(methodindex);
if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
continue;
@@ -1212,15 +1182,16 @@ void Generator::generateStaticMetacall()
fprintf(out, " {\n");
fprintf(out, " using _t = %s (%s::*)(",f.type.rawName.constData() , cdef->classname.constData());
- int argsCount = f.arguments.count();
- for (int j = 0; j < argsCount; ++j) {
- const ArgumentDef &a = f.arguments.at(j);
- if (j)
+ const auto begin = f.arguments.cbegin();
+ const auto end = f.arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
fprintf(out, ", ");
fprintf(out, "%s", QByteArray(a.type.name + ' ' + a.rightType).constData());
}
if (f.isPrivateSignal) {
- if (argsCount > 0)
+ if (!f.arguments.isEmpty())
fprintf(out, ", ");
fprintf(out, "%s", "QPrivateSignal");
}
@@ -1228,7 +1199,7 @@ void Generator::generateStaticMetacall()
fprintf(out, ") const;\n");
else
fprintf(out, ");\n");
- fprintf(out, " if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&%s::%s)) {\n",
+ fprintf(out, " if (_t _q_method = &%s::%s; *reinterpret_cast<_t *>(_a[1]) == _q_method) {\n",
cdef->classname.constData(), f.name.constData());
fprintf(out, " *result = %d;\n", methodindex);
fprintf(out, " return;\n");
@@ -1260,7 +1231,7 @@ void Generator::generateStaticMetacall()
fprintf(out, " *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< %s >(); break;\n", lastKey.constData());
}
fprintf(out, " }\n");
- fprintf(out, " }\n");
+ fprintf(out, " } ");
isUsed_a = true;
needElse = true;
}
@@ -1271,8 +1242,7 @@ void Generator::generateStaticMetacall()
bool needSet = false;
bool needReset = false;
bool hasBindableProperties = false;
- for (int i = 0; i < cdef->propertyList.size(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ for (const PropertyDef &p : std::as_const(cdef->propertyList)) {
needGet |= !p.read.isEmpty() || !p.member.isEmpty();
if (!p.read.isEmpty() || !p.member.isEmpty())
needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
@@ -1282,10 +1252,8 @@ void Generator::generateStaticMetacall()
needReset |= !p.reset.isEmpty();
hasBindableProperties |= !p.bind.isEmpty();
}
- fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
-
if (needElse)
- fprintf(out, "else ");
+ fprintf(out, " else ");
fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
auto setupMemberAccess = [this]() {
@@ -1305,7 +1273,7 @@ void Generator::generateStaticMetacall()
if (needTempVarForGet)
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.read.isEmpty() && p.member.isEmpty())
continue;
@@ -1323,6 +1291,9 @@ void Generator::generateStaticMetacall()
else if (cdef->enumDeclarations.value(p.type, false))
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
propindex, prefix.constData(), p.read.constData());
+ else if (p.read == "default")
+ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s().value(); break;\n",
+ propindex, p.type.constData(), prefix.constData(), p.bind.constData());
else if (!p.read.isEmpty())
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
propindex, p.type.constData(), prefix.constData(), p.read.constData());
@@ -1343,7 +1314,7 @@ void Generator::generateStaticMetacall()
setupMemberAccess();
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.constant)
continue;
@@ -1356,6 +1327,12 @@ void Generator::generateStaticMetacall()
if (cdef->enumDeclarations.value(p.type, false)) {
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
propindex, prefix.constData(), p.write.constData());
+ } else if (p.write == "default") {
+ fprintf(out, " case %d: {\n", propindex);
+ fprintf(out, " %s%s().setValue(*reinterpret_cast< %s*>(_v));\n",
+ prefix.constData(), p.bind.constData(), p.type.constData());
+ fprintf(out, " break;\n");
+ fprintf(out, " }\n");
} else if (!p.write.isEmpty()) {
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
propindex, prefix.constData(), p.write.constData(), p.type.constData());
@@ -1390,15 +1367,15 @@ void Generator::generateStaticMetacall()
if (needReset) {
setupMemberAccess();
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
- if (!p.reset.endsWith(')'))
+ if (p.reset.isEmpty())
continue;
QByteArray prefix = "_t->";
if (p.inPrivateClass.size()) {
prefix += p.inPrivateClass + "->";
}
- fprintf(out, " case %d: %s%s; break;\n",
+ fprintf(out, " case %d: %s%s(); break;\n",
propindex, prefix.constData(), p.reset.constData());
}
fprintf(out, " default: break;\n");
@@ -1411,7 +1388,7 @@ void Generator::generateStaticMetacall()
if (hasBindableProperties) {
setupMemberAccess();
fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ for (int propindex = 0; propindex < int(cdef->propertyList.size()); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
if (p.bind.isEmpty())
continue;
@@ -1428,7 +1405,6 @@ void Generator::generateStaticMetacall()
fprintf(out, " }\n");
}
fprintf(out, " }");
- fprintf(out, "\n#endif // QT_NO_PROPERTIES");
needElse = true;
}
@@ -1445,10 +1421,10 @@ void Generator::generateStaticMetacall()
if (!isUsed_a)
fprintf(out, " (void)_a;\n");
- fprintf(out, "}\n\n");
+ fprintf(out, "}\n");
}
-void Generator::generateSignal(FunctionDef *def,int index)
+void Generator::generateSignal(const FunctionDef *def, int index)
{
if (def->wasCloned || def->isAbstract)
return;
@@ -1472,9 +1448,11 @@ void Generator::generateSignal(FunctionDef *def,int index)
}
int offset = 1;
- for (int j = 0; j < def->arguments.count(); ++j) {
- const ArgumentDef &a = def->arguments.at(j);
- if (j)
+ const auto begin = def->arguments.cbegin();
+ const auto end = def->arguments.cend();
+ for (auto it = begin; it != end; ++it) {
+ const ArgumentDef &a = *it;
+ if (it != begin)
fputs(", ", out);
if (a.type.name.size())
fputs(a.type.name.constData(), out);
@@ -1505,7 +1483,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
}
int i;
for (i = 1; i < offset; ++i)
- if (i <= def->arguments.count() && def->arguments.at(i - 1).type.isVolatile)
+ if (i <= def->arguments.size() && def->arguments.at(i - 1).type.isVolatile)
fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(std::addressof(_t%d)))", i);
else
fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t%d)))", i);
@@ -1564,8 +1542,7 @@ static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v)
return cbor_encode_double(parent, d);
}
}
- Q_UNREACHABLE();
- return CborUnknownError;
+ Q_UNREACHABLE_RETURN(CborUnknownError);
}
void Generator::generatePluginMetaData()
@@ -1617,7 +1594,7 @@ void Generator::generatePluginMetaData()
};
// 'Use' all namespaces.
- int pos = cdef->qualified.indexOf("::");
+ qsizetype pos = cdef->qualified.indexOf("::");
for ( ; pos != -1 ; pos = cdef->qualified.indexOf("::", pos + 2) )
fprintf(out, "using namespace %s;\n", cdef->qualified.left(pos).constData());
@@ -1632,7 +1609,7 @@ void Generator::generatePluginMetaData()
// compatibility with Qt 6.0-6.2
fprintf(out, "#else\nQT_PLUGIN_METADATA_SECTION\n"
- "static constexpr unsigned char qt_pluginMetaData_%s[] = {\n"
+ "Q_CONSTINIT static constexpr unsigned char qt_pluginMetaData_%s[] = {\n"
" 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',\n"
" // metadata version, Qt version, architectural requirements\n"
" 0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),",
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 35128cb543..2d4d69ca05 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef GENERATOR_H
#define GENERATOR_H
@@ -35,16 +10,19 @@ QT_BEGIN_NAMESPACE
class Generator
{
+ Moc *parser = nullptr;
FILE *out;
ClassDef *cdef;
QList<uint> meta_data;
public:
- Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr,
bool requireCompleteTypes = false);
void generateCode();
+ qsizetype registeredStringsCount() { return strings.size(); };
+
private:
bool registerableMetaType(const QByteArray &propertyType);
void registerClassInfoStrings();
@@ -62,7 +40,7 @@ private:
void generateProperties();
void generateMetacall();
void generateStaticMetacall();
- void generateSignal(FunctionDef *def, int index);
+ void generateSignal(const FunctionDef *def, int index);
void generatePluginMetaData();
QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
QMap<int, QMultiMap<QByteArray, int>>
diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp
index c87fbca4f4..6a1f58490f 100644
--- a/src/tools/moc/keywords.cpp
+++ b/src/tools/moc/keywords.cpp
@@ -1,41 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// auto generated
// DO NOT EDIT.
static const short keyword_trans[][128] = {
- {0,0,0,0,0,0,0,0,0,586,583,0,0,0,0,0,
+ {0,0,0,0,0,0,0,0,0,618,615,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 586,252,584,587,8,38,239,585,25,26,236,234,30,235,27,237,
+ 618,252,616,619,8,38,239,617,25,26,236,234,30,235,27,237,
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,21,8,8,8,8,8,8,8,8,8,31,589,32,238,8,
+ 8,21,8,8,8,8,8,8,8,8,8,31,621,32,238,8,
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -116,7 +91,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,290,222,0,0,504,0,0,0,
+ 0,0,0,0,0,0,0,0,290,222,0,0,524,0,0,0,
0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -155,7 +130,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,528,0,0,0,0,0,0,0,0,0,0,357,
+ 0,0,0,0,401,0,0,0,0,0,0,0,0,0,0,357,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -177,7 +152,7 @@ static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
- 592,592,592,592,592,592,592,592,592,592,0,0,0,0,0,0,
+ 624,624,624,624,624,624,624,624,624,624,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -336,7 +311,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,591,0,0,0,0,590,
+ 0,0,0,0,0,0,0,0,0,0,623,0,0,0,0,622,
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -372,21 +347,21 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,501,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
+ 0,521,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,482,431,415,423,380,0,491,0,0,0,572,364,358,
- 393,0,564,479,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,502,451,435,443,380,0,511,0,0,0,604,364,358,
+ 393,0,596,499,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,401,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,421,0,0,0,
0,0,394,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -394,7 +369,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,518,0,0,0,0,0,395,
+ 0,0,0,0,0,0,0,0,0,538,0,0,0,0,0,395,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -402,48 +377,64 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,403,0,0,0,0,0,0,0,0,0,0,0,548,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,419,0,0,0,0,0,0,0,0,0,0,0,420,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,582,0,0,0,0,0,415,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,427,0,0,0,0,0,0,0,0,0,0,0,428,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,461,439,0,0,444,0,0,0,453,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,439,0,0,0,0,0,0,0,0,0,0,0,440,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,547,0,480,0,0,0,508,0,0,514,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,447,0,0,0,0,0,0,0,0,0,0,0,448,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,481,459,0,0,464,0,0,0,473,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,493,0,540,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,565,0,500,0,0,0,528,0,0,534,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 556,0,0,524,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,513,0,558,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 574,0,0,544,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
@@ -857,193 +848,225 @@ static const struct
{CHARACTER, 0, 84, 399, CHARACTER},
{CHARACTER, 0, 89, 400, CHARACTER},
{Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 85, 402, CHARACTER},
- {CHARACTER, 0, 71, 403, CHARACTER},
- {CHARACTER, 0, 73, 404, CHARACTER},
- {CHARACTER, 0, 78, 405, CHARACTER},
- {CHARACTER, 0, 95, 406, CHARACTER},
- {CHARACTER, 0, 77, 407, CHARACTER},
- {CHARACTER, 0, 69, 408, CHARACTER},
- {CHARACTER, 0, 84, 409, CHARACTER},
- {CHARACTER, 0, 65, 410, CHARACTER},
- {CHARACTER, 0, 68, 411, CHARACTER},
- {CHARACTER, 0, 65, 412, CHARACTER},
- {CHARACTER, 0, 84, 413, CHARACTER},
- {CHARACTER, 0, 65, 414, CHARACTER},
+ {CHARACTER, 0, 95, 402, CHARACTER},
+ {CHARACTER, 46, 0, 0, CHARACTER},
+ {CHARACTER, 0, 78, 404, CHARACTER},
+ {CHARACTER, 0, 79, 405, CHARACTER},
+ {CHARACTER, 0, 78, 406, CHARACTER},
+ {CHARACTER, 0, 89, 407, CHARACTER},
+ {CHARACTER, 0, 77, 408, CHARACTER},
+ {CHARACTER, 0, 79, 409, CHARACTER},
+ {CHARACTER, 0, 85, 410, CHARACTER},
+ {CHARACTER, 0, 83, 411, CHARACTER},
+ {CHARACTER, 0, 95, 412, CHARACTER},
+ {CHARACTER, 0, 80, 413, CHARACTER},
+ {CHARACTER, 0, 82, 414, CHARACTER},
+ {CHARACTER, 47, 0, 0, CHARACTER},
+ {CHARACTER, 0, 80, 416, CHARACTER},
+ {CHARACTER, 0, 69, 417, CHARACTER},
+ {CHARACTER, 0, 82, 418, CHARACTER},
+ {CHARACTER, 0, 84, 419, CHARACTER},
+ {CHARACTER, 0, 89, 420, CHARACTER},
+ {QT_ANONYMOUS_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 85, 422, CHARACTER},
+ {CHARACTER, 0, 71, 423, CHARACTER},
+ {CHARACTER, 0, 73, 424, CHARACTER},
+ {CHARACTER, 0, 78, 425, CHARACTER},
+ {CHARACTER, 0, 95, 426, CHARACTER},
+ {CHARACTER, 0, 77, 427, CHARACTER},
+ {CHARACTER, 0, 69, 428, CHARACTER},
+ {CHARACTER, 0, 84, 429, CHARACTER},
+ {CHARACTER, 0, 65, 430, CHARACTER},
+ {CHARACTER, 0, 68, 431, CHARACTER},
+ {CHARACTER, 0, 65, 432, CHARACTER},
+ {CHARACTER, 0, 84, 433, CHARACTER},
+ {CHARACTER, 0, 65, 434, CHARACTER},
{Q_PLUGIN_METADATA_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 416, CHARACTER},
- {CHARACTER, 0, 85, 417, CHARACTER},
- {CHARACTER, 0, 77, 418, CHARACTER},
- {Q_ENUM_TOKEN, 46, 0, 0, CHARACTER},
+ {CHARACTER, 0, 78, 436, CHARACTER},
+ {CHARACTER, 0, 85, 437, CHARACTER},
+ {CHARACTER, 0, 77, 438, CHARACTER},
+ {Q_ENUM_TOKEN, 48, 0, 0, CHARACTER},
{Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 421, CHARACTER},
- {CHARACTER, 0, 83, 422, CHARACTER},
+ {CHARACTER, 0, 78, 441, CHARACTER},
+ {CHARACTER, 0, 83, 442, CHARACTER},
{Q_ENUM_NS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 424, CHARACTER},
- {CHARACTER, 0, 65, 425, CHARACTER},
- {CHARACTER, 0, 71, 426, CHARACTER},
- {Q_FLAG_TOKEN, 47, 0, 0, CHARACTER},
+ {CHARACTER, 0, 76, 444, CHARACTER},
+ {CHARACTER, 0, 65, 445, CHARACTER},
+ {CHARACTER, 0, 71, 446, CHARACTER},
+ {Q_FLAG_TOKEN, 49, 0, 0, CHARACTER},
{Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 429, CHARACTER},
- {CHARACTER, 0, 83, 430, CHARACTER},
+ {CHARACTER, 0, 78, 449, CHARACTER},
+ {CHARACTER, 0, 83, 450, CHARACTER},
{Q_FLAG_NS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 432, CHARACTER},
- {CHARACTER, 0, 67, 433, CHARACTER},
- {CHARACTER, 0, 76, 434, CHARACTER},
- {CHARACTER, 0, 65, 435, CHARACTER},
- {CHARACTER, 0, 82, 436, CHARACTER},
- {CHARACTER, 0, 69, 437, CHARACTER},
- {CHARACTER, 0, 95, 438, CHARACTER},
- {CHARACTER, 48, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 440, CHARACTER},
- {CHARACTER, 0, 65, 441, CHARACTER},
- {CHARACTER, 0, 71, 442, CHARACTER},
- {CHARACTER, 0, 83, 443, CHARACTER},
- {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 78, 445, CHARACTER},
- {CHARACTER, 0, 84, 446, CHARACTER},
- {CHARACTER, 0, 69, 447, CHARACTER},
- {CHARACTER, 0, 82, 448, CHARACTER},
- {CHARACTER, 0, 70, 449, CHARACTER},
- {CHARACTER, 0, 65, 450, CHARACTER},
- {CHARACTER, 0, 67, 451, CHARACTER},
{CHARACTER, 0, 69, 452, CHARACTER},
- {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 454, CHARACTER},
- {CHARACTER, 0, 84, 455, CHARACTER},
- {CHARACTER, 0, 65, 456, CHARACTER},
- {CHARACTER, 0, 84, 457, CHARACTER},
- {CHARACTER, 0, 89, 458, CHARACTER},
- {CHARACTER, 0, 80, 459, CHARACTER},
- {CHARACTER, 0, 69, 460, CHARACTER},
- {Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 88, 462, CHARACTER},
- {CHARACTER, 0, 84, 463, CHARACTER},
- {CHARACTER, 0, 69, 464, CHARACTER},
+ {CHARACTER, 0, 67, 453, CHARACTER},
+ {CHARACTER, 0, 76, 454, CHARACTER},
+ {CHARACTER, 0, 65, 455, CHARACTER},
+ {CHARACTER, 0, 82, 456, CHARACTER},
+ {CHARACTER, 0, 69, 457, CHARACTER},
+ {CHARACTER, 0, 95, 458, CHARACTER},
+ {CHARACTER, 50, 0, 0, CHARACTER},
+ {CHARACTER, 0, 76, 460, CHARACTER},
+ {CHARACTER, 0, 65, 461, CHARACTER},
+ {CHARACTER, 0, 71, 462, CHARACTER},
+ {CHARACTER, 0, 83, 463, CHARACTER},
+ {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 465, CHARACTER},
- {CHARACTER, 0, 83, 466, CHARACTER},
- {CHARACTER, 0, 73, 467, CHARACTER},
- {CHARACTER, 0, 79, 468, CHARACTER},
- {CHARACTER, 0, 78, 469, CHARACTER},
- {CHARACTER, 0, 95, 470, CHARACTER},
- {CHARACTER, 0, 73, 471, CHARACTER},
- {CHARACTER, 0, 78, 472, CHARACTER},
- {CHARACTER, 0, 84, 473, CHARACTER},
+ {CHARACTER, 0, 84, 466, CHARACTER},
+ {CHARACTER, 0, 69, 467, CHARACTER},
+ {CHARACTER, 0, 82, 468, CHARACTER},
+ {CHARACTER, 0, 70, 469, CHARACTER},
+ {CHARACTER, 0, 65, 470, CHARACTER},
+ {CHARACTER, 0, 67, 471, CHARACTER},
+ {CHARACTER, 0, 69, 472, CHARACTER},
+ {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 474, CHARACTER},
- {CHARACTER, 0, 82, 475, CHARACTER},
- {CHARACTER, 0, 70, 476, CHARACTER},
- {CHARACTER, 0, 65, 477, CHARACTER},
- {CHARACTER, 0, 67, 478, CHARACTER},
- {CHARACTER, 0, 69, 452, CHARACTER},
- {CHARACTER, 49, 0, 0, CHARACTER},
- {CHARACTER, 0, 84, 481, CHARACTER},
- {CHARACTER, 0, 83, 427, CHARACTER},
- {CHARACTER, 0, 76, 483, CHARACTER},
- {CHARACTER, 0, 65, 484, CHARACTER},
- {CHARACTER, 0, 83, 485, CHARACTER},
+ {CHARACTER, 0, 84, 475, CHARACTER},
+ {CHARACTER, 0, 65, 476, CHARACTER},
+ {CHARACTER, 0, 84, 477, CHARACTER},
+ {CHARACTER, 0, 89, 478, CHARACTER},
+ {CHARACTER, 0, 80, 479, CHARACTER},
+ {CHARACTER, 0, 69, 480, CHARACTER},
+ {Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 88, 482, CHARACTER},
+ {CHARACTER, 0, 84, 483, CHARACTER},
+ {CHARACTER, 0, 69, 484, CHARACTER},
+ {CHARACTER, 0, 78, 485, CHARACTER},
{CHARACTER, 0, 83, 486, CHARACTER},
{CHARACTER, 0, 73, 487, CHARACTER},
- {CHARACTER, 0, 78, 488, CHARACTER},
- {CHARACTER, 0, 70, 489, CHARACTER},
- {CHARACTER, 0, 79, 490, CHARACTER},
- {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 79, 488, CHARACTER},
+ {CHARACTER, 0, 78, 489, CHARACTER},
+ {CHARACTER, 0, 95, 490, CHARACTER},
+ {CHARACTER, 0, 73, 491, CHARACTER},
{CHARACTER, 0, 78, 492, CHARACTER},
- {CHARACTER, 50, 0, 0, CHARACTER},
+ {CHARACTER, 0, 84, 493, CHARACTER},
{CHARACTER, 0, 69, 494, CHARACTER},
{CHARACTER, 0, 82, 495, CHARACTER},
{CHARACTER, 0, 70, 496, CHARACTER},
{CHARACTER, 0, 65, 497, CHARACTER},
{CHARACTER, 0, 67, 498, CHARACTER},
- {CHARACTER, 0, 69, 499, CHARACTER},
- {CHARACTER, 0, 83, 500, CHARACTER},
+ {CHARACTER, 0, 69, 472, CHARACTER},
+ {CHARACTER, 51, 0, 0, CHARACTER},
+ {CHARACTER, 0, 84, 501, CHARACTER},
+ {CHARACTER, 0, 83, 447, CHARACTER},
+ {CHARACTER, 0, 76, 503, CHARACTER},
+ {CHARACTER, 0, 65, 504, CHARACTER},
+ {CHARACTER, 0, 83, 505, CHARACTER},
+ {CHARACTER, 0, 83, 506, CHARACTER},
+ {CHARACTER, 0, 73, 507, CHARACTER},
+ {CHARACTER, 0, 78, 508, CHARACTER},
+ {CHARACTER, 0, 70, 509, CHARACTER},
+ {CHARACTER, 0, 79, 510, CHARACTER},
+ {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 78, 512, CHARACTER},
+ {CHARACTER, 52, 0, 0, CHARACTER},
+ {CHARACTER, 0, 69, 514, CHARACTER},
+ {CHARACTER, 0, 82, 515, CHARACTER},
+ {CHARACTER, 0, 70, 516, CHARACTER},
+ {CHARACTER, 0, 65, 517, CHARACTER},
+ {CHARACTER, 0, 67, 518, CHARACTER},
+ {CHARACTER, 0, 69, 519, CHARACTER},
+ {CHARACTER, 0, 83, 520, CHARACTER},
{Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 108, 502, CHARACTER},
- {CHARACTER, 0, 115, 503, CHARACTER},
+ {CHARACTER, 0, 108, 522, CHARACTER},
+ {CHARACTER, 0, 115, 523, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 111, 505, CHARACTER},
- {CHARACTER, 0, 116, 506, CHARACTER},
- {CHARACTER, 0, 115, 507, CHARACTER},
+ {CHARACTER, 0, 111, 525, CHARACTER},
+ {CHARACTER, 0, 116, 526, CHARACTER},
+ {CHARACTER, 0, 115, 527, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 71, 509, CHARACTER},
- {CHARACTER, 0, 78, 510, CHARACTER},
- {CHARACTER, 0, 65, 511, CHARACTER},
- {CHARACTER, 0, 76, 512, CHARACTER},
- {Q_SIGNAL_TOKEN, 0, 83, 513, CHARACTER},
+ {CHARACTER, 0, 71, 529, CHARACTER},
+ {CHARACTER, 0, 78, 530, CHARACTER},
+ {CHARACTER, 0, 65, 531, CHARACTER},
+ {CHARACTER, 0, 76, 532, CHARACTER},
+ {Q_SIGNAL_TOKEN, 0, 83, 533, CHARACTER},
{Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 515, CHARACTER},
- {CHARACTER, 0, 84, 516, CHARACTER},
- {Q_SLOT_TOKEN, 0, 83, 517, CHARACTER},
+ {CHARACTER, 0, 79, 535, CHARACTER},
+ {CHARACTER, 0, 84, 536, CHARACTER},
+ {Q_SLOT_TOKEN, 0, 83, 537, CHARACTER},
{Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 86, 519, CHARACTER},
- {CHARACTER, 0, 65, 520, CHARACTER},
- {CHARACTER, 0, 84, 521, CHARACTER},
- {CHARACTER, 0, 69, 522, CHARACTER},
- {CHARACTER, 0, 95, 523, CHARACTER},
- {CHARACTER, 51, 0, 0, CHARACTER},
- {CHARACTER, 0, 76, 525, CHARACTER},
- {CHARACTER, 0, 79, 526, CHARACTER},
- {CHARACTER, 0, 84, 527, CHARACTER},
+ {CHARACTER, 0, 86, 539, CHARACTER},
+ {CHARACTER, 0, 65, 540, CHARACTER},
+ {CHARACTER, 0, 84, 541, CHARACTER},
+ {CHARACTER, 0, 69, 542, CHARACTER},
+ {CHARACTER, 0, 95, 543, CHARACTER},
+ {CHARACTER, 53, 0, 0, CHARACTER},
+ {CHARACTER, 0, 76, 545, CHARACTER},
+ {CHARACTER, 0, 79, 546, CHARACTER},
+ {CHARACTER, 0, 84, 547, CHARACTER},
{Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 95, 529, CHARACTER},
- {CHARACTER, 0, 77, 530, CHARACTER},
- {CHARACTER, 0, 79, 531, CHARACTER},
- {CHARACTER, 0, 67, 532, CHARACTER},
- {CHARACTER, 0, 95, 533, CHARACTER},
- {CHARACTER, 0, 67, 534, CHARACTER},
- {CHARACTER, 0, 79, 535, CHARACTER},
- {CHARACTER, 0, 77, 536, CHARACTER},
- {CHARACTER, 0, 80, 537, CHARACTER},
- {CHARACTER, 0, 65, 538, CHARACTER},
- {CHARACTER, 0, 84, 539, CHARACTER},
+ {CHARACTER, 0, 79, 549, CHARACTER},
+ {CHARACTER, 0, 67, 550, CHARACTER},
+ {CHARACTER, 0, 95, 551, CHARACTER},
+ {CHARACTER, 0, 67, 552, CHARACTER},
+ {CHARACTER, 0, 79, 553, CHARACTER},
+ {CHARACTER, 0, 77, 554, CHARACTER},
+ {CHARACTER, 0, 80, 555, CHARACTER},
+ {CHARACTER, 0, 65, 556, CHARACTER},
+ {CHARACTER, 0, 84, 557, CHARACTER},
{Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 541, CHARACTER},
- {CHARACTER, 0, 75, 542, CHARACTER},
- {CHARACTER, 0, 65, 543, CHARACTER},
- {CHARACTER, 0, 66, 544, CHARACTER},
- {CHARACTER, 0, 76, 545, CHARACTER},
- {CHARACTER, 0, 69, 546, CHARACTER},
+ {CHARACTER, 0, 79, 559, CHARACTER},
+ {CHARACTER, 0, 75, 560, CHARACTER},
+ {CHARACTER, 0, 65, 561, CHARACTER},
+ {CHARACTER, 0, 66, 562, CHARACTER},
+ {CHARACTER, 0, 76, 563, CHARACTER},
+ {CHARACTER, 0, 69, 564, CHARACTER},
{Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 82, 548, CHARACTER},
- {CHARACTER, 0, 73, 549, CHARACTER},
- {CHARACTER, 0, 80, 550, CHARACTER},
- {CHARACTER, 0, 84, 551, CHARACTER},
- {CHARACTER, 0, 65, 552, CHARACTER},
- {CHARACTER, 0, 66, 553, CHARACTER},
- {CHARACTER, 0, 76, 554, CHARACTER},
- {CHARACTER, 0, 69, 555, CHARACTER},
+ {CHARACTER, 0, 82, 566, CHARACTER},
+ {CHARACTER, 0, 73, 567, CHARACTER},
+ {CHARACTER, 0, 80, 568, CHARACTER},
+ {CHARACTER, 0, 84, 569, CHARACTER},
+ {CHARACTER, 0, 65, 570, CHARACTER},
+ {CHARACTER, 0, 66, 571, CHARACTER},
+ {CHARACTER, 0, 76, 572, CHARACTER},
+ {CHARACTER, 0, 69, 573, CHARACTER},
{Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 82, 557, CHARACTER},
- {CHARACTER, 0, 79, 558, CHARACTER},
- {CHARACTER, 0, 80, 559, CHARACTER},
- {CHARACTER, 0, 69, 560, CHARACTER},
- {CHARACTER, 0, 82, 561, CHARACTER},
- {CHARACTER, 0, 84, 562, CHARACTER},
- {CHARACTER, 0, 89, 563, CHARACTER},
+ {CHARACTER, 0, 82, 575, CHARACTER},
+ {CHARACTER, 0, 79, 576, CHARACTER},
+ {CHARACTER, 0, 80, 577, CHARACTER},
+ {CHARACTER, 0, 69, 578, CHARACTER},
+ {CHARACTER, 0, 82, 579, CHARACTER},
+ {CHARACTER, 0, 84, 580, CHARACTER},
+ {CHARACTER, 0, 89, 581, CHARACTER},
{Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 69, 565, CHARACTER},
- {CHARACTER, 0, 86, 566, CHARACTER},
- {CHARACTER, 0, 73, 567, CHARACTER},
- {CHARACTER, 0, 83, 568, CHARACTER},
- {CHARACTER, 0, 73, 569, CHARACTER},
- {CHARACTER, 0, 79, 570, CHARACTER},
- {CHARACTER, 0, 78, 571, CHARACTER},
+ {CHARACTER, 0, 86, 583, CHARACTER},
+ {CHARACTER, 0, 65, 584, CHARACTER},
+ {CHARACTER, 0, 84, 585, CHARACTER},
+ {CHARACTER, 0, 69, 586, CHARACTER},
+ {CHARACTER, 0, 95, 587, CHARACTER},
+ {CHARACTER, 0, 80, 588, CHARACTER},
+ {CHARACTER, 0, 82, 589, CHARACTER},
+ {CHARACTER, 0, 79, 590, CHARACTER},
+ {CHARACTER, 0, 80, 591, CHARACTER},
+ {CHARACTER, 0, 69, 592, CHARACTER},
+ {CHARACTER, 0, 82, 593, CHARACTER},
+ {CHARACTER, 0, 84, 594, CHARACTER},
+ {CHARACTER, 0, 89, 595, CHARACTER},
+ {QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 69, 597, CHARACTER},
+ {CHARACTER, 0, 86, 598, CHARACTER},
+ {CHARACTER, 0, 73, 599, CHARACTER},
+ {CHARACTER, 0, 83, 600, CHARACTER},
+ {CHARACTER, 0, 73, 601, CHARACTER},
+ {CHARACTER, 0, 79, 602, CHARACTER},
+ {CHARACTER, 0, 78, 603, CHARACTER},
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 573, CHARACTER},
- {CHARACTER, 0, 67, 574, CHARACTER},
- {CHARACTER, 0, 95, 575, CHARACTER},
- {CHARACTER, 0, 73, 576, CHARACTER},
- {CHARACTER, 0, 78, 577, CHARACTER},
- {CHARACTER, 0, 67, 578, CHARACTER},
- {CHARACTER, 0, 76, 579, CHARACTER},
- {CHARACTER, 0, 85, 580, CHARACTER},
- {CHARACTER, 0, 68, 581, CHARACTER},
- {CHARACTER, 0, 69, 582, CHARACTER},
+ {CHARACTER, 0, 79, 605, CHARACTER},
+ {CHARACTER, 0, 67, 606, CHARACTER},
+ {CHARACTER, 0, 95, 607, CHARACTER},
+ {CHARACTER, 0, 73, 608, CHARACTER},
+ {CHARACTER, 0, 78, 609, CHARACTER},
+ {CHARACTER, 0, 67, 610, CHARACTER},
+ {CHARACTER, 0, 76, 611, CHARACTER},
+ {CHARACTER, 0, 85, 612, CHARACTER},
+ {CHARACTER, 0, 68, 613, CHARACTER},
+ {CHARACTER, 0, 69, 614, CHARACTER},
{Q_MOC_INCLUDE_TOKEN, 0, 0, 0, CHARACTER},
{NEWLINE, 0, 0, 0, NOTOKEN},
{QUOTE, 0, 0, 0, NOTOKEN},
{SINGLEQUOTE, 0, 0, 0, NOTOKEN},
{WHITESPACE, 0, 0, 0, NOTOKEN},
- {HASH, 0, 35, 588, HASH},
+ {HASH, 0, 35, 620, HASH},
{PP_HASHHASH, 0, 0, 0, NOTOKEN},
{BACKSLASH, 0, 0, 0, NOTOKEN},
{CPP_COMMENT, 0, 0, 0, NOTOKEN},
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index 3e98fbf2b8..bb51352519 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** 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 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <depfile_shared.h>
#include "preprocessor.h"
@@ -48,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*
This function looks at two file names and returns the name of the
infile with a path relative to outfile.
@@ -153,7 +130,7 @@ static QStringList argumentsFromCommandLineAndFile(const QStringList &arguments,
allArguments.reserve(arguments.size());
for (const QString &argument : arguments) {
// "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
- if (argument.startsWith(QLatin1Char('@'))) {
+ if (argument.startsWith(u'@')) {
QString optionsFile = argument;
optionsFile.remove(0, 1);
if (optionsFile.isEmpty()) {
@@ -306,6 +283,10 @@ int runMoc(int argc, char **argv)
jsonOption.setDescription(QStringLiteral("In addition to generating C++ code, create a machine-readable JSON file in a file that matches the output file and an extra .json extension."));
parser.addOption(jsonOption);
+ QCommandLineOption debugIncludesOption(QStringLiteral("debug-includes"));
+ debugIncludesOption.setDescription(QStringLiteral("Display debug messages of each considered include path."));
+ parser.addOption(debugIncludesOption);
+
QCommandLineOption collectOption(QStringLiteral("collect-json"));
collectOption.setDescription(QStringLiteral("Instead of processing C++ code, collect previously generated JSON output into a single file."));
parser.addOption(collectOption);
@@ -349,8 +330,8 @@ int runMoc(int argc, char **argv)
if (parser.isSet(collectOption))
return collectJson(files, output, hasOptionFiles);
- if (files.count() > 1) {
- error(qPrintable(QLatin1String("Too many input files specified: '") + files.join(QLatin1String("' '")) + QLatin1Char('\'')));
+ if (files.size() > 1) {
+ error(qPrintable("Too many input files specified: '"_L1 + files.join("' '"_L1) + u'\''));
parser.showHelp(1);
} else if (!files.isEmpty()) {
filename = files.first();
@@ -358,6 +339,7 @@ int runMoc(int argc, char **argv)
const bool ignoreConflictingOptions = parser.isSet(ignoreConflictsOption);
pp.preprocessOnly = parser.isSet(preprocessOption);
+ pp.setDebugIncludes(parser.isSet(debugIncludesOption));
if (parser.isSet(noIncludeOption)) {
moc.noInclude = true;
autoInclude = false;
@@ -385,7 +367,7 @@ int runMoc(int argc, char **argv)
for (const QString &path : includePaths)
pp.includes += Preprocessor::IncludePath(QFile::encodeName(path));
QString compilerFlavor = parser.value(compilerFlavorOption);
- if (compilerFlavor.isEmpty() || compilerFlavor == QLatin1String("unix")) {
+ if (compilerFlavor.isEmpty() || compilerFlavor == "unix"_L1) {
// traditional Unix compilers use both CPATH and CPLUS_INCLUDE_PATH
// $CPATH feeds to #include <...> and #include "...", whereas
// CPLUS_INCLUDE_PATH is equivalent to GCC's -isystem, so we parse later
@@ -395,14 +377,14 @@ int runMoc(int argc, char **argv)
const auto cplus_include_path = qgetenv("CPLUS_INCLUDE_PATH").split(QDir::listSeparator().toLatin1());
for (const QByteArray &p : cplus_include_path)
pp.includes += Preprocessor::IncludePath(p);
- } else if (compilerFlavor == QLatin1String("msvc")) {
+ } else if (compilerFlavor == "msvc"_L1) {
// MSVC uses one environment variable: INCLUDE
const auto include = qgetenv("INCLUDE").split(QDir::listSeparator().toLatin1());
for (const QByteArray &p : include)
pp.includes += Preprocessor::IncludePath(p);
} else {
- error(qPrintable(QLatin1String("Unknown compiler flavor '") + compilerFlavor +
- QLatin1String("'; valid values are: msvc, unix.")));
+ error(qPrintable("Unknown compiler flavor '"_L1 + compilerFlavor +
+ "'; valid values are: msvc, unix."_L1));
parser.showHelp(1);
}
@@ -417,7 +399,7 @@ int runMoc(int argc, char **argv)
for (const QString &arg : defines) {
QByteArray name = arg.toLocal8Bit();
QByteArray value("1");
- int eq = name.indexOf('=');
+ const qsizetype eq = name.indexOf('=');
if (eq >= 0) {
value = name.mid(eq + 1);
name = name.left(eq);
@@ -441,16 +423,16 @@ int runMoc(int argc, char **argv)
pp.macros.remove(macro);
}
const QStringList noNotesCompatValues = parser.values(noNotesWarningsCompatOption);
- if (parser.isSet(noNotesOption) || noNotesCompatValues.contains(QLatin1String("n")))
+ if (parser.isSet(noNotesOption) || noNotesCompatValues.contains("n"_L1))
moc.displayNotes = false;
- if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains(QLatin1String("w")))
+ if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains("w"_L1))
moc.displayWarnings = moc.displayNotes = false;
if (autoInclude) {
- int spos = filename.lastIndexOf(QDir::separator());
- int ppos = filename.lastIndexOf(QLatin1Char('.'));
+ qsizetype spos = filename.lastIndexOf(QDir::separator());
+ qsizetype ppos = filename.lastIndexOf(u'.');
// spos >= -1 && ppos > spos => ppos >= 0
- moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != QLatin1Char('h'));
+ moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != u'h');
}
if (defaultInclude) {
if (moc.includePath.isEmpty()) {
@@ -467,11 +449,14 @@ int runMoc(int argc, char **argv)
if (filename.isEmpty()) {
filename = QStringLiteral("standard input");
- in.open(stdin, QIODevice::ReadOnly);
+ if (!in.open(stdin, QIODevice::ReadOnly)) {
+ fprintf(stderr, "moc: cannot open standard input: %s\n", qPrintable(in.errorString()));
+ return 1;
+ }
} else {
in.setFileName(filename);
if (!in.open(QIODevice::ReadOnly)) {
- fprintf(stderr, "moc: %s: No such file\n", qPrintable(filename));
+ fprintf(stderr, "moc: cannot open %s: %s\n", qPrintable(filename), qPrintable(in.errorString()));
return 1;
}
moc.filename = filename.toLocal8Bit();
@@ -479,13 +464,13 @@ int runMoc(int argc, char **argv)
const auto metadata = parser.values(metadataOption);
for (const QString &md : metadata) {
- int split = md.indexOf(QLatin1Char('='));
+ qsizetype split = md.indexOf(u'=');
QString key = md.left(split);
QString value = md.mid(split + 1);
if (split == -1 || key.isEmpty() || value.isEmpty()) {
error("missing key or value for option '-M'");
- } else if (key.indexOf(QLatin1Char('.')) != -1) {
+ } else if (key.indexOf(u'.') != -1) {
// Don't allow keys with '.' for now, since we might need this
// format later for more advanced meta data API
error("A key cannot contain the letter '.' for option '-M'");
@@ -499,6 +484,17 @@ int runMoc(int argc, char **argv)
moc.currentFilenames.push(filename.toLocal8Bit());
moc.includes = pp.includes;
+ if (Q_UNLIKELY(parser.isSet(debugIncludesOption))) {
+ fprintf(stderr, "debug-includes: include search list:\n");
+
+ for (auto &includePath : pp.includes) {
+ fprintf(stderr, "debug-includes: '%s' framework: %d \n",
+ includePath.path.constData(),
+ includePath.isFrameworkPath);
+ }
+ fprintf(stderr, "debug-includes: end of search list.\n");
+ }
+
// 1. preprocess
const auto includeFiles = parser.values(includeOption);
QStringList validIncludesFiles;
@@ -543,12 +539,15 @@ int runMoc(int argc, char **argv)
if (!out)
#endif
{
- fprintf(stderr, "moc: Cannot create %s\n", QFile::encodeName(output).constData());
+ const auto fopen_errno = errno;
+ fprintf(stderr, "moc: Cannot create %s. Error: %s\n",
+ QFile::encodeName(output).constData(),
+ strerror(fopen_errno));
return 1;
}
if (parser.isSet(jsonOption)) {
- const QString jsonOutputFileName = output + QLatin1String(".json");
+ const QString jsonOutputFileName = output + ".json"_L1;
FILE *f;
#if defined(_MSC_VER)
if (_wfopen_s(&f, reinterpret_cast<const wchar_t *>(jsonOutputFileName.utf16()), L"w") != 0)
@@ -556,9 +555,12 @@ int runMoc(int argc, char **argv)
f = fopen(QFile::encodeName(jsonOutputFileName).constData(), "w");
if (!f)
#endif
- fprintf(stderr, "moc: Cannot create JSON output file %s. %s\n",
+ {
+ const auto fopen_errno = errno;
+ fprintf(stderr, "moc: Cannot create JSON output file %s. Error: %s\n",
QFile::encodeName(jsonOutputFileName).constData(),
- strerror(errno));
+ strerror(fopen_errno));
+ }
jsonOutput.reset(f);
}
} else { // use stdout
@@ -589,7 +591,7 @@ int runMoc(int argc, char **argv)
if (parser.isSet(depFilePathOption)) {
depOutputFileName = parser.value(depFilePathOption);
} else if (outputToFile) {
- depOutputFileName = output + QLatin1String(".d");
+ depOutputFileName = output + ".d"_L1;
} else {
fprintf(stderr, "moc: Writing to stdout, but no depfile path specified.\n");
}
@@ -603,9 +605,12 @@ int runMoc(int argc, char **argv)
depFileHandleRaw = fopen(QFile::encodeName(depOutputFileName).constData(), "w");
if (!depFileHandleRaw)
#endif
- fprintf(stderr, "moc: Cannot create dep output file '%s'. %s\n",
+ {
+ const auto fopen_errno = errno;
+ fprintf(stderr, "moc: Cannot create dep output file '%s'. Error: %s\n",
QFile::encodeName(depOutputFileName).constData(),
- strerror(errno));
+ strerror(fopen_errno));
+ }
depFileHandle.reset(depFileHandleRaw);
if (!depFileHandle.isNull()) {
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 3b3c325cfc..3cbe331f14 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
-** 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) 2021 The Qt Company Ltd.
+// Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "moc.h"
#include "generator.h"
@@ -43,12 +18,23 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// only moc needs this function
static QByteArray normalizeType(const QByteArray &ba)
{
return ba.size() ? normalizeTypeInternal(ba.constBegin(), ba.constEnd()) : ba;
}
+const QByteArray &Moc::toFullyQualified(const QByteArray &name) const noexcept
+{
+ if (auto it = knownQObjectClasses.find(name); it != knownQObjectClasses.end())
+ return it.value();
+ if (auto it = knownGadgets.find(name); it != knownGadgets.end())
+ return it.value();
+ return name;
+}
+
bool Moc::parseClassHead(ClassDef *def)
{
// figure out whether this is a class declaration, or only a
@@ -63,6 +49,9 @@ bool Moc::parseClassHead(ClassDef *def)
return false;
} while (token);
+ // support attributes like "class [[deprecated]]] name"
+ skipCxxAttributes();
+
if (!test(IDENTIFIER)) // typedef struct { ... }
return false;
QByteArray name = lexem();
@@ -107,17 +96,17 @@ bool Moc::parseClassHead(ClassDef *def)
else
test(PUBLIC);
test(VIRTUAL);
- const QByteArray type = parseType().name;
+ const Type type = parseType();
// ignore the 'class Foo : BAR(Baz)' case
if (test(LPAREN)) {
until(RPAREN);
} else {
- def->superclassList += qMakePair(type, access);
+ def->superclassList.push_back({type.name, toFullyQualified(type.name), access});
}
} while (test(COMMA));
if (!def->superclassList.isEmpty()
- && knownGadgets.contains(def->superclassList.constFirst().first)) {
+ && knownGadgets.contains(def->superclassList.constFirst().classname)) {
// Q_GADGET subclasses are treated as Q_GADGETs
knownGadgets.insert(def->classname, def->qualified);
knownGadgets.insert(def->qualified, def->qualified);
@@ -263,7 +252,7 @@ bool Moc::parseEnum(EnumDef *def)
}
if (test(COLON)) { // C++11 strongly typed enum
// enum Foo : unsigned long { ... };
- parseType(); //ignore the result
+ def->type = normalizeType(parseType().name);
}
if (!test(LBRACE))
return false;
@@ -320,7 +309,7 @@ void Moc::parseFunctionArguments(FunctionDef *def)
arg.rightType += lexem();
}
arg.normalizedType = normalizeType(QByteArray(arg.type.name + ' ' + arg.rightType));
- arg.typeNameForCast = normalizeType(QByteArray(noRef(arg.type.name) + "(*)" + arg.rightType));
+ arg.typeNameForCast = QByteArray("std::add_pointer_t<"+arg.normalizedType+">");
if (test(EQ))
arg.isDefault = true;
def->arguments += arg;
@@ -338,6 +327,9 @@ void Moc::parseFunctionArguments(FunctionDef *def)
def->arguments.removeLast();
def->isRawSlot = true;
}
+
+ if (Q_UNLIKELY(def->arguments.size() >= std::numeric_limits<int>::max()))
+ error("number of function arguments exceeds std::numeric_limits<int>::max()");
}
bool Moc::testFunctionAttribute(FunctionDef *def)
@@ -388,7 +380,7 @@ QTypeRevision Moc::parseRevision()
revisionString.remove(0, 1);
revisionString.chop(1);
const QList<QByteArray> majorMinor = revisionString.split(',');
- switch (majorMinor.length()) {
+ switch (majorMinor.size()) {
case 1: {
bool ok = false;
const int revision = revisionString.toInt(&ok);
@@ -429,8 +421,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
def->isVirtual = false;
def->isStatic = false;
//skip modifiers and attributes
- while (test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) ||
- (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual
+ while (testForFunctionModifiers(def)
|| skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {}
bool templateFunction = (lookup() == TEMPLATE);
def->type = parseType();
@@ -441,31 +432,29 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
error();
}
bool scopedFunctionName = false;
- if (test(LPAREN)) {
- def->name = def->type.name;
- scopedFunctionName = def->type.isScoped;
- def->type = Type("int");
- } else {
- Type tempType = parseType();;
- while (!tempType.name.isEmpty() && lookup() != LPAREN) {
- if (testFunctionAttribute(def->type.firstToken, def))
- ; // fine
- else if (def->type.firstToken == Q_SIGNALS_TOKEN)
- error();
- else if (def->type.firstToken == Q_SLOTS_TOKEN)
- error();
- else {
- if (!def->tag.isEmpty())
- def->tag += ' ';
- def->tag += def->type.name;
- }
- def->type = tempType;
- tempType = parseType();
+ // we might have modifiers and attributes after a tag
+ // note that testFunctionAttribute is handled further below,
+ // and revisions and attributes must come first
+ while (testForFunctionModifiers(def)) {}
+ Type tempType = parseType();
+ while (!tempType.name.isEmpty() && lookup() != LPAREN) {
+ if (testFunctionAttribute(def->type.firstToken, def))
+ ; // fine
+ else if (def->type.firstToken == Q_SIGNALS_TOKEN)
+ error();
+ else if (def->type.firstToken == Q_SLOTS_TOKEN)
+ error();
+ else {
+ if (!def->tag.isEmpty())
+ def->tag += ' ';
+ def->tag += def->type.name;
}
- next(LPAREN, "Not a signal or slot declaration");
- def->name = tempType.name;
- scopedFunctionName = tempType.isScoped;
+ def->type = tempType;
+ tempType = parseType();
}
+ next(LPAREN, "Not a signal or slot declaration");
+ def->name = tempType.name;
+ scopedFunctionName = tempType.isScoped;
if (!test(RPAREN)) {
parseFunctionArguments(def);
@@ -529,14 +518,20 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
return true;
}
+bool Moc::testForFunctionModifiers(FunctionDef *def)
+{
+ return test(EXPLICIT) || test(INLINE) ||
+ (test(STATIC) && (def->isStatic = true)) ||
+ (test(VIRTUAL) && (def->isVirtual = true));
+}
+
// like parseFunction, but never aborts with an error
bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
{
def->isVirtual = false;
def->isStatic = false;
//skip modifiers and attributes
- while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) ||
- (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual
+ while (testForFunctionModifiers(def)
|| skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {}
bool tilde = test(TILDE);
def->type = parseType();
@@ -551,10 +546,15 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
def->isConstructor = !tilde;
def->type = Type();
} else {
- def->type = Type("int");
+ // missing type name? => Skip
+ return false;
}
} else {
- Type tempType = parseType();;
+ // ### TODO: The condition before testForFunctionModifiers shoulnd't be necessary,
+ // but otherwise we end up with misparses
+ if (def->isSlot || def->isSignal || def->isInvokable)
+ while (testForFunctionModifiers(def)) {}
+ Type tempType = parseType();
while (!tempType.name.isEmpty() && lookup() != LPAREN) {
if (testFunctionAttribute(def->type.firstToken, def))
; // fine
@@ -601,6 +601,63 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
return true;
}
+inline void handleDefaultArguments(QList<FunctionDef> *functionList, FunctionDef &function)
+{
+ // support a function with a default argument by pretending there is an
+ // overload without the argument (the original function is the overload with
+ // all arguments present)
+ while (function.arguments.size() > 0 && function.arguments.constLast().isDefault) {
+ function.wasCloned = true;
+ function.arguments.removeLast();
+ *functionList += function;
+ }
+}
+
+void Moc::prependNamespaces(BaseDef &def, const QList<NamespaceDef> &namespaceList) const
+{
+ auto it = namespaceList.crbegin();
+ const auto rend = namespaceList.crend();
+ for (; it != rend; ++it) {
+ if (inNamespace(&*it))
+ def.qualified.prepend(it->classname + "::");
+ }
+}
+
+void Moc::checkListSizes(const ClassDef &def)
+{
+ if (Q_UNLIKELY(def.nonClassSignalList.size() > std::numeric_limits<int>::max()))
+ error("number of signals defined in parent class(es) exceeds "
+ "std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.propertyList.size() > std::numeric_limits<int>::max()))
+ error("number of bindable properties exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.classInfoList.size() > std::numeric_limits<int>::max()))
+ error("number of times Q_CLASSINFO macro is used exceeds "
+ "std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.enumList.size() > std::numeric_limits<int>::max()))
+ error("number of enumerations exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.superclassList.size() > std::numeric_limits<int>::max()))
+ error("number of super classes exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.constructorList.size() > std::numeric_limits<int>::max()))
+ error("number of constructor parameters exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.signalList.size() > std::numeric_limits<int>::max()))
+ error("number of signals exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.slotList.size() > std::numeric_limits<int>::max()))
+ error("number of declared slots exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.methodList.size() > std::numeric_limits<int>::max()))
+ error("number of methods exceeds std::numeric_limits<int>::max().");
+
+ if (Q_UNLIKELY(def.publicList.size() > std::numeric_limits<int>::max()))
+ error("number of public functions declared in this class exceeds "
+ "std::numeric_limits<int>::max().");
+}
void Moc::parse()
{
@@ -610,11 +667,17 @@ void Moc::parse()
Token t = next();
switch (t) {
case NAMESPACE: {
- int rewind = index;
+ qsizetype rewind = index;
if (test(IDENTIFIER)) {
QByteArray nsName = lexem();
QByteArrayList nested;
while (test(SCOPE)) {
+ /* treat (C++20's) namespace A::inline B {} as A::B
+ this is mostly to not break compilation when encountering such
+ a construct in a header; the interaction of Qt's meta-macros with
+ inline namespaces is still rather poor.
+ */
+ test(INLINE);
next(IDENTIFIER);
nested.append(nsName);
nsName = lexem();
@@ -636,11 +699,8 @@ void Moc::parse()
def.end = index;
index = def.begin + 1;
- for (int i = namespaceList.size() - 1; i >= 0; --i) {
- if (inNamespace(&namespaceList.at(i))) {
- def.qualified.prepend(namespaceList.at(i).classname + "::");
- }
- }
+ prependNamespaces(def, namespaceList);
+
for (const QByteArray &ns : nested) {
NamespaceDef parentNs;
parentNs.classname = ns;
@@ -655,8 +715,10 @@ void Moc::parse()
switch (next()) {
case NAMESPACE:
if (test(IDENTIFIER)) {
- while (test(SCOPE))
+ while (test(SCOPE)) {
+ test(INLINE); // ignore inline namespaces
next(IDENTIFIER);
+ }
if (test(EQ)) {
// namespace Foo = Bar::Baz;
until(SEMIC);
@@ -786,9 +848,7 @@ void Moc::parse()
if (!def.hasQObject && !def.hasQGadget)
continue;
- for (int i = namespaceList.size() - 1; i >= 0; --i)
- if (inNamespace(&namespaceList.at(i)))
- def.qualified.prepend(namespaceList.at(i).classname + "::");
+ prependNamespaces(def, namespaceList);
QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets;
classHash.insert(def.classname, def.qualified);
@@ -801,10 +861,9 @@ void Moc::parse()
continue;
ClassDef def;
if (parseClassHead(&def)) {
+ prependNamespaces(def, namespaceList);
+
FunctionDef::Access access = FunctionDef::Private;
- for (int i = namespaceList.size() - 1; i >= 0; --i)
- if (inNamespace(&namespaceList.at(i)))
- def.qualified.prepend(namespaceList.at(i).classname + "::");
while (inClass(&def) && hasNext()) {
switch ((t = next())) {
case PRIVATE:
@@ -865,7 +924,10 @@ void Moc::parse()
error("Template classes not supported by Q_GADGET");
break;
case Q_PROPERTY_TOKEN:
- parseProperty(&def);
+ parseProperty(&def, Named);
+ break;
+ case QT_ANONYMOUS_PROPERTY_TOKEN:
+ parseProperty(&def, Anonymous);
break;
case Q_PLUGIN_METADATA_TOKEN:
parsePluginData(&def);
@@ -900,7 +962,10 @@ void Moc::parse()
parseSlotInPrivate(&def, access);
break;
case Q_PRIVATE_PROPERTY_TOKEN:
- parsePrivateProperty(&def);
+ parsePrivateProperty(&def, Named);
+ break;
+ case QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN:
+ parsePrivateProperty(&def, Anonymous);
break;
case ENUM: {
EnumDef enumDef;
@@ -913,16 +978,12 @@ void Moc::parse()
default:
FunctionDef funcDef;
funcDef.access = access;
- int rewind = index--;
+ qsizetype rewind = index--;
if (parseMaybeFunction(&def, &funcDef)) {
if (funcDef.isConstructor) {
if ((access == FunctionDef::Public) && funcDef.isInvokable) {
def.constructorList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.constructorList += funcDef;
- }
+ handleDefaultArguments(&def.constructorList, funcDef);
}
} else if (funcDef.isDestructor) {
// don't care about destructors
@@ -931,29 +992,17 @@ void Moc::parse()
def.publicList += funcDef;
if (funcDef.isSlot) {
def.slotList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.slotList += funcDef;
- }
+ handleDefaultArguments(&def.slotList, funcDef);
if (funcDef.revision > 0)
++def.revisionedMethods;
} else if (funcDef.isSignal) {
def.signalList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.signalList += funcDef;
- }
+ handleDefaultArguments(&def.signalList, funcDef);
if (funcDef.revision > 0)
++def.revisionedMethods;
} else if (funcDef.isInvokable) {
def.methodList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def.methodList += funcDef;
- }
+ handleDefaultArguments(&def.methodList, funcDef);
if (funcDef.revision > 0)
++def.revisionedMethods;
}
@@ -978,16 +1027,20 @@ void Moc::parse()
if (!def.pluginData.iid.isEmpty())
def.pluginData.metaArgs = metaArgs;
- checkSuperClasses(&def);
+ if (def.hasQObject && !def.superclassList.isEmpty())
+ checkSuperClasses(&def);
+
checkProperties(&def);
+ checkListSizes(def);
+
classList += def;
QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets;
classHash.insert(def.classname, def.qualified);
classHash.insert(def.qualified, def.qualified);
}
}
- for (const auto &n : qAsConst(namespaceList)) {
+ for (const auto &n : std::as_const(namespaceList)) {
if (!n.hasQNamespace)
continue;
ClassDef def;
@@ -1000,8 +1053,10 @@ void Moc::parse()
if (it != classList.end()) {
it->classInfoList += def.classInfoList;
+ Q_ASSERT(it->classInfoList.size() <= std::numeric_limits<int>::max());
it->enumDeclarations.insert(def.enumDeclarations);
it->enumList += def.enumList;
+ Q_ASSERT(it->enumList.size() <= std::numeric_limits<int>::max());
it->flagAliases.insert(def.flagAliases);
} else {
knownGadgets.insert(def.classname, def.qualified);
@@ -1079,25 +1134,27 @@ static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes)
void Moc::generate(FILE *out, FILE *jsonOutput)
{
- QByteArray fn = filename;
- int i = filename.length()-1;
- while (i > 0 && filename.at(i - 1) != '/' && filename.at(i - 1) != '\\')
- --i; // skip path
- if (i >= 0)
- fn = filename.mid(i);
+ QByteArrayView fn = QByteArrayView(filename);
+
+ auto isSlash = [](char ch) { return ch == '/' || ch == '\\'; };
+ auto rit = std::find_if(fn.crbegin(), fn.crend(), isSlash);
+ if (rit != fn.crend())
+ fn = fn.last(rit - fn.crbegin());
+
fprintf(out, "/****************************************************************************\n"
"** Meta object code from reading C++ file '%s'\n**\n" , fn.constData());
fprintf(out, "** Created by: The Qt Meta Object Compiler version %d (Qt %s)\n**\n" , mocOutputRevision, QT_VERSION_STR);
fprintf(out, "** WARNING! All changes made in this file will be lost!\n"
"*****************************************************************************/\n\n");
- fprintf(out, "#include <memory>\n"); // For std::addressof
+ // include header(s) of user class definitions at _first_ to allow
+ // for preprocessor definitions possibly affecting standard headers.
+ // see https://codereview.qt-project.org/c/qt/qtbase/+/445937
if (!noInclude) {
if (includePath.size() && !includePath.endsWith('/'))
includePath += '/';
- for (int i = 0; i < includeFiles.size(); ++i) {
- QByteArray inc = includeFiles.at(i);
- if (inc.at(0) != '<' && inc.at(0) != '"') {
+ for (QByteArray inc : std::as_const(includeFiles)) {
+ if (!inc.isEmpty() && inc.at(0) != '<' && inc.at(0) != '"') {
if (includePath.size() && includePath != "./")
inc.prepend(includePath);
inc = '\"' + inc + '\"';
@@ -1108,7 +1165,6 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
if (classList.size() && classList.constFirst().classname == "Qt")
fprintf(out, "#include <QtCore/qobject.h>\n");
- fprintf(out, "#include <QtCore/qbytearray.h>\n"); // For QByteArrayData
fprintf(out, "#include <QtCore/qmetatype.h>\n"); // For QMetaType::Type
if (mustIncludeQPluginH)
fprintf(out, "#include <QtCore/qplugin.h>\n");
@@ -1117,6 +1173,10 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
for (const QByteArray &qtContainer : qtContainers)
fprintf(out, "#include <QtCore/%s>\n", qtContainer.constData());
+ fprintf(out, "\n#include <QtCore/qtmochelpers.h>\n");
+
+ fprintf(out, "\n#include <memory>\n\n"); // For std::addressof
+ fprintf(out, "\n#include <QtCore/qxptype_traits.h>\n"); // is_detected
fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n"
"#error \"The header file '%s' doesn't include <QObject>.\"\n", fn.constData());
@@ -1127,32 +1187,44 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
" much.)\"\n", QT_VERSION_STR);
fprintf(out, "#endif\n\n");
- fprintf(out, "QT_BEGIN_MOC_NAMESPACE\n");
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+ fprintf(out, "#ifndef Q_CONSTINIT\n"
+ "#define Q_CONSTINIT\n"
+ "#endif\n\n");
+#endif
+
fprintf(out, "QT_WARNING_PUSH\n");
fprintf(out, "QT_WARNING_DISABLE_DEPRECATED\n");
+ fprintf(out, "QT_WARNING_DISABLE_GCC(\"-Wuseless-cast\")\n");
fputs("", out);
- for (i = 0; i < classList.size(); ++i) {
- Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out, requireCompleteTypes);
+ for (ClassDef &def : classList) {
+ Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets, out,
+ requireCompleteTypes);
generator.generateCode();
+
+ // generator.generateCode() should have already registered all strings
+ if (Q_UNLIKELY(generator.registeredStringsCount() >= std::numeric_limits<int>::max())) {
+ error("internal limit exceeded: number of parsed strings is too big.");
+ exit(EXIT_FAILURE);
+ }
}
fputs("", out);
fprintf(out, "QT_WARNING_POP\n");
- fprintf(out, "QT_END_MOC_NAMESPACE\n");
if (jsonOutput) {
QJsonObject mocData;
- mocData[QLatin1String("outputRevision")] = mocOutputRevision;
- mocData[QLatin1String("inputFile")] = QLatin1String(fn.constData());
+ mocData["outputRevision"_L1] = mocOutputRevision;
+ mocData["inputFile"_L1] = QLatin1StringView(fn.constData());
QJsonArray classesJsonFormatted;
- for (const ClassDef &cdef: qAsConst(classList))
+ for (const ClassDef &cdef: std::as_const(classList))
classesJsonFormatted.append(cdef.toJson());
if (!classesJsonFormatted.isEmpty())
- mocData[QLatin1String("classes")] = classesJsonFormatted;
+ mocData["classes"_L1] = classesJsonFormatted;
QJsonDocument jsonDoc(mocData);
fputs(jsonDoc.toJson().constData(), jsonOutput);
@@ -1197,11 +1269,7 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access)
++def->revisionedMethods;
}
def->slotList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def->slotList += funcDef;
- }
+ handleDefaultArguments(&def->slotList, funcDef);
}
}
@@ -1245,15 +1313,11 @@ void Moc::parseSignals(ClassDef *def)
++def->revisionedMethods;
}
def->signalList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def->signalList += funcDef;
- }
+ handleDefaultArguments(&def->signalList, funcDef);
}
}
-void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex)
+void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex, Moc::PropertyMode mode)
{
propDef.location = index;
propDef.relativeIndex = propertyIndex;
@@ -1283,8 +1347,10 @@ void Moc::createPropertyDef(PropertyDef &propDef, int propertyIndex)
propDef.type = type;
- next();
- propDef.name = lexem();
+ if (mode == Moc::Named) {
+ next();
+ propDef.name = lexem();
+ }
parsePropertyAttributes(propDef);
}
@@ -1301,7 +1367,8 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
};
while (test(IDENTIFIER)) {
- const QByteArray l = lexem();
+ const Symbol &lsym = symbol();
+ const QByteArray l = lsym.lexem();
if (l[0] == 'C' && l == "CONSTANT") {
propDef.constant = true;
continue;
@@ -1324,11 +1391,15 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
QByteArray v, v2;
if (test(LPAREN)) {
v = lexemUntil(RPAREN);
- v = v.mid(1, v.length() - 2); // removes the '(' and ')'
+ v = v.mid(1, v.size() - 2); // removes the '(' and ')'
} else if (test(INTEGER_LITERAL)) {
v = lexem();
if (l != "REVISION")
- error(1);
+ error(lsym);
+ } else if (test(DEFAULT)) {
+ v = lexem();
+ if (l != "READ" && l != "WRITE")
+ error(lsym);
} else {
next(IDENTIFIER);
v = lexem();
@@ -1342,21 +1413,21 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
if (l == "MEMBER")
propDef.member = v;
else
- error(2);
+ error(lsym);
break;
case 'R':
if (l == "READ")
propDef.read = v;
else if (l == "RESET")
- propDef.reset = v + v2;
+ propDef.reset = v;
else if (l == "REVISION") {
bool ok = false;
const int minor = v.toInt(&ok);
if (!ok || !QTypeRevision::isValidSegment(minor))
- error(1);
+ error(lsym);
propDef.revision = QTypeRevision::fromMinorVersion(minor).toEncodedVersion<int>();
} else
- error(2);
+ error(lsym);
break;
case 'S':
if (l == "SCRIPTABLE") {
@@ -1366,27 +1437,27 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
propDef.stored = v + v2;
checkIsFunction(propDef.stored, "STORED");
} else
- error(2);
+ error(lsym);
break;
- case 'W': if (l != "WRITE") error(2);
+ case 'W': if (l != "WRITE") error(lsym);
propDef.write = v;
break;
- case 'B': if (l != "BINDABLE") error(2);
+ case 'B': if (l != "BINDABLE") error(lsym);
propDef.bind = v;
break;
- case 'D': if (l != "DESIGNABLE") error(2);
+ case 'D': if (l != "DESIGNABLE") error(lsym);
propDef.designable = v + v2;
checkIsFunction(propDef.designable, "DESIGNABLE");
break;
- case 'N': if (l != "NOTIFY") error(2);
+ case 'N': if (l != "NOTIFY") error(lsym);
propDef.notify = v;
break;
- case 'U': if (l != "USER") error(2);
+ case 'U': if (l != "USER") error(lsym);
propDef.user = v + v2;
checkIsFunction(propDef.user, "USER");
break;
default:
- error(2);
+ error(lsym);
}
}
if (propDef.constant && !propDef.write.isNull()) {
@@ -1407,13 +1478,25 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
propDef.constant = false;
warning(msg.constData());
}
+ if (propDef.read == "default" && propDef.bind.isNull()) {
+ const QByteArray msg = "Property declaration " + propDef.name
+ + " is not BINDable but default-READable. READ will be ignored.";
+ propDef.read = "";
+ warning(msg.constData());
+ }
+ if (propDef.write == "default" && propDef.bind.isNull()) {
+ const QByteArray msg = "Property declaration " + propDef.name
+ + " is not BINDable but default-WRITEable. WRITE will be ignored.";
+ propDef.write = "";
+ warning(msg.constData());
+ }
}
-void Moc::parseProperty(ClassDef *def)
+void Moc::parseProperty(ClassDef *def, Moc::PropertyMode mode)
{
next(LPAREN);
PropertyDef propDef;
- createPropertyDef(propDef, int(def->propertyList.size()));
+ createPropertyDef(propDef, int(def->propertyList.size()), mode);
next(RPAREN);
def->propertyList += propDef;
@@ -1434,9 +1517,11 @@ void Moc::parsePluginData(ClassDef *def)
} else if (l == "FILE") {
next(STRING_LITERAL);
QByteArray metaDataFile = unquotedLexem();
- QFileInfo fi(QFileInfo(QString::fromLocal8Bit(currentFilenames.top().constData())).dir(), QString::fromLocal8Bit(metaDataFile.constData()));
- for (int j = 0; j < includes.size() && !fi.exists(); ++j) {
- const IncludePath &p = includes.at(j);
+ QFileInfo fi(QFileInfo(QString::fromLocal8Bit(currentFilenames.top())).dir(),
+ QString::fromLocal8Bit(metaDataFile));
+ for (const IncludePath &p : std::as_const(includes)) {
+ if (fi.exists())
+ break;
if (p.isFrameworkPath)
continue;
@@ -1499,7 +1584,7 @@ QByteArray Moc::parsePropertyAccessor()
return accessor;
}
-void Moc::parsePrivateProperty(ClassDef *def)
+void Moc::parsePrivateProperty(ClassDef *def, Moc::PropertyMode mode)
{
next(LPAREN);
PropertyDef propDef;
@@ -1507,7 +1592,7 @@ void Moc::parsePrivateProperty(ClassDef *def)
next(COMMA);
- createPropertyDef(propDef, int(def->propertyList.size()));
+ createPropertyDef(propDef, int(def->propertyList.size()), mode);
def->propertyList += propDef;
}
@@ -1605,7 +1690,7 @@ void Moc::parseInterfaces(ClassDef *def)
}
}
// resolve from classnames to interface ids
- for (int i = 0; i < iface.count(); ++i) {
+ for (qsizetype i = 0; i < iface.size(); ++i) {
const QByteArray iid = interface2IdMap.value(iface.at(i).className);
if (iid.isEmpty())
error("Undefined interface");
@@ -1674,11 +1759,7 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
funcDef.access = access;
parseFunction(&funcDef, true);
def->slotList += funcDef;
- while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
- funcDef.wasCloned = true;
- funcDef.arguments.removeLast();
- def->slotList += funcDef;
- }
+ handleDefaultArguments(&def->slotList, funcDef);
if (funcDef.revision > 0)
++def->revisionedMethods;
@@ -1686,7 +1767,7 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
QByteArray Moc::lexemUntil(Token target)
{
- int from = index;
+ qsizetype from = index;
until(target);
QByteArray s;
while (from <= index) {
@@ -1722,7 +1803,7 @@ bool Moc::until(Token target) {
//when searching commas within the default argument, we should take care of template depth (anglecount)
// unfortunately, we do not have enough semantic information to know if '<' is the operator< or
// the beginning of a template type. so we just use heuristics.
- int possible = -1;
+ qsizetype possible = -1;
while (index < symbols.size()) {
Token t = symbols.at(index++).token;
@@ -1786,7 +1867,8 @@ bool Moc::until(Token target) {
void Moc::checkSuperClasses(ClassDef *def)
{
- const QByteArray firstSuperclass = def->superclassList.value(0).first;
+ Q_ASSERT(!def->superclassList.isEmpty());
+ const QByteArray &firstSuperclass = def->superclassList.at(0).classname;
if (!knownQObjectClasses.contains(firstSuperclass)) {
// enable once we /require/ include paths
@@ -1801,8 +1883,18 @@ void Moc::checkSuperClasses(ClassDef *def)
#endif
return;
}
- for (int i = 1; i < def->superclassList.count(); ++i) {
- const QByteArray superClass = def->superclassList.at(i).first;
+
+ auto isRegisteredInterface = [&def](QByteArrayView super) {
+ auto matchesSuperClass = [&super](const auto &ifaces) {
+ return !ifaces.isEmpty() && ifaces.first().className == super;
+ };
+ return std::any_of(def->interfaceList.cbegin(), def->interfaceList.cend(), matchesSuperClass);
+ };
+
+ const auto end = def->superclassList.cend();
+ auto it = def->superclassList.cbegin() + 1;
+ for (; it != end; ++it) {
+ const QByteArray &superClass = it->classname;
if (knownQObjectClasses.contains(superClass)) {
const QByteArray msg
= "Class "
@@ -1816,14 +1908,7 @@ void Moc::checkSuperClasses(ClassDef *def)
}
if (interface2IdMap.contains(superClass)) {
- bool registeredInterface = false;
- for (int i = 0; i < def->interfaceList.count(); ++i)
- if (def->interfaceList.at(i).constFirst().className == superClass) {
- registeredInterface = true;
- break;
- }
-
- if (!registeredInterface) {
+ if (!isRegisteredInterface(superClass)) {
const QByteArray msg
= "Class "
+ def->classname
@@ -1844,31 +1929,27 @@ void Moc::checkProperties(ClassDef *cdef)
// specify get function, for compatibility we accept functions
// returning pointers, or const char * for QByteArray.
//
- QDuplicateTracker<QByteArray> definedProperties(cdef->propertyList.count());
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- PropertyDef &p = cdef->propertyList[i];
+ QDuplicateTracker<QByteArray> definedProperties(cdef->propertyList.size());
+ auto hasNoAttributes = [&](const PropertyDef &p) {
if (definedProperties.hasSeen(p.name)) {
QByteArray msg = "The property '" + p.name + "' is defined multiple times in class " + cdef->classname + ".";
warning(msg.constData());
}
if (p.read.isEmpty() && p.member.isEmpty() && p.bind.isEmpty()) {
- const int rewind = index;
- if (p.location >= 0)
- index = p.location;
QByteArray msg = "Property declaration " + p.name + " has neither an associated QProperty<> member"
", nor a READ accessor function nor an associated MEMBER variable. The property will be invalid.";
- warning(msg.constData());
- index = rewind;
- if (p.write.isEmpty()) {
- cdef->propertyList.removeAt(i);
- --i;
- }
- continue;
+ const auto &sym = p.location >= 0 ? symbolAt(p.location) : Symbol();
+ warning(sym, msg.constData());
+ if (p.write.isEmpty())
+ return true;
}
+ return false;
+ };
+ cdef->propertyList.removeIf(hasNoAttributes);
- for (int j = 0; j < cdef->publicList.count(); ++j) {
- const FunctionDef &f = cdef->publicList.at(j);
+ for (PropertyDef &p : cdef->propertyList) {
+ for (const FunctionDef &f : std::as_const(cdef->publicList)) {
if (f.name != p.read)
continue;
if (!f.isConst) // get functions must be const
@@ -1894,7 +1975,7 @@ void Moc::checkProperties(ClassDef *cdef)
}
if (!p.notify.isEmpty()) {
int notifyId = -1;
- for (int j = 0; j < cdef->signalList.count(); ++j) {
+ for (int j = 0; j < int(cdef->signalList.size()); ++j) {
const FunctionDef &f = cdef->signalList.at(j);
if (f.name != p.notify) {
continue;
@@ -1905,12 +1986,12 @@ void Moc::checkProperties(ClassDef *cdef)
}
p.notifyId = notifyId;
if (notifyId == -1) {
- int index = cdef->nonClassSignalList.indexOf(p.notify);
+ const int index = int(cdef->nonClassSignalList.indexOf(p.notify));
if (index == -1) {
cdef->nonClassSignalList << p.notify;
- p.notifyId = -1 - cdef->nonClassSignalList.count();
+ p.notifyId = int(-1 - cdef->nonClassSignalList.size());
} else {
- p.notifyId = -2 - index;
+ p.notifyId = int(-2 - index);
}
}
}
@@ -1920,19 +2001,19 @@ void Moc::checkProperties(ClassDef *cdef)
QJsonObject ClassDef::toJson() const
{
QJsonObject cls;
- cls[QLatin1String("className")] = QString::fromUtf8(classname.constData());
- cls[QLatin1String("qualifiedClassName")] = QString::fromUtf8(qualified.constData());
+ cls["className"_L1] = QString::fromUtf8(classname.constData());
+ cls["qualifiedClassName"_L1] = QString::fromUtf8(qualified.constData());
QJsonArray classInfos;
- for (const auto &info: qAsConst(classInfoList)) {
+ for (const auto &info: std::as_const(classInfoList)) {
QJsonObject infoJson;
- infoJson[QLatin1String("name")] = QString::fromUtf8(info.name);
- infoJson[QLatin1String("value")] = QString::fromUtf8(info.value);
+ infoJson["name"_L1] = QString::fromUtf8(info.name);
+ infoJson["value"_L1] = QString::fromUtf8(info.value);
classInfos.append(infoJson);
}
if (classInfos.size())
- cls[QLatin1String("classInfos")] = classInfos;
+ cls["classInfos"_L1] = classInfos;
const auto appendFunctions = [&cls](const QString &type, const QList<FunctionDef> &funcs) {
QJsonArray jsonFuncs;
@@ -1944,59 +2025,59 @@ QJsonObject ClassDef::toJson() const
cls[type] = jsonFuncs;
};
- appendFunctions(QLatin1String("signals"), signalList);
- appendFunctions(QLatin1String("slots"), slotList);
- appendFunctions(QLatin1String("constructors"), constructorList);
- appendFunctions(QLatin1String("methods"), methodList);
+ appendFunctions("signals"_L1, signalList);
+ appendFunctions("slots"_L1, slotList);
+ appendFunctions("constructors"_L1, constructorList);
+ appendFunctions("methods"_L1, methodList);
QJsonArray props;
- for (const PropertyDef &propDef: qAsConst(propertyList))
+ for (const PropertyDef &propDef: std::as_const(propertyList))
props.append(propDef.toJson());
if (!props.isEmpty())
- cls[QLatin1String("properties")] = props;
+ cls["properties"_L1] = props;
if (hasQObject)
- cls[QLatin1String("object")] = true;
+ cls["object"_L1] = true;
if (hasQGadget)
- cls[QLatin1String("gadget")] = true;
+ cls["gadget"_L1] = true;
if (hasQNamespace)
- cls[QLatin1String("namespace")] = true;
+ cls["namespace"_L1] = true;
QJsonArray superClasses;
- for (const auto &super: qAsConst(superclassList)) {
- const auto name = super.first;
- const auto access = super.second;
+ for (const auto &super: std::as_const(superclassList)) {
QJsonObject superCls;
- superCls[QLatin1String("name")] = QString::fromUtf8(name);
- FunctionDef::accessToJson(&superCls, access);
+ superCls["name"_L1] = QString::fromUtf8(super.classname);
+ if (super.classname != super.qualified)
+ superCls["fullyQualifiedName"_L1] = QString::fromUtf8(super.qualified);
+ FunctionDef::accessToJson(&superCls, super.access);
superClasses.append(superCls);
}
if (!superClasses.isEmpty())
- cls[QLatin1String("superClasses")] = superClasses;
+ cls["superClasses"_L1] = superClasses;
QJsonArray enums;
- for (const EnumDef &enumDef: qAsConst(enumList))
+ for (const EnumDef &enumDef: std::as_const(enumList))
enums.append(enumDef.toJson(*this));
if (!enums.isEmpty())
- cls[QLatin1String("enums")] = enums;
+ cls["enums"_L1] = enums;
QJsonArray ifaces;
for (const QList<Interface> &ifaceList : interfaceList) {
QJsonArray jsonList;
for (const Interface &iface: ifaceList) {
QJsonObject ifaceJson;
- ifaceJson[QLatin1String("id")] = QString::fromUtf8(iface.interfaceId);
- ifaceJson[QLatin1String("className")] = QString::fromUtf8(iface.className);
+ ifaceJson["id"_L1] = QString::fromUtf8(iface.interfaceId);
+ ifaceJson["className"_L1] = QString::fromUtf8(iface.className);
jsonList.append(ifaceJson);
}
ifaces.append(jsonList);
}
if (!ifaces.isEmpty())
- cls[QLatin1String("interfaces")] = ifaces;
+ cls["interfaces"_L1] = ifaces;
return cls;
}
@@ -2004,22 +2085,25 @@ QJsonObject ClassDef::toJson() const
QJsonObject FunctionDef::toJson() const
{
QJsonObject fdef;
- fdef[QLatin1String("name")] = QString::fromUtf8(name);
+ fdef["name"_L1] = QString::fromUtf8(name);
if (!tag.isEmpty())
- fdef[QLatin1String("tag")] = QString::fromUtf8(tag);
- fdef[QLatin1String("returnType")] = QString::fromUtf8(normalizedType);
+ fdef["tag"_L1] = QString::fromUtf8(tag);
+ fdef["returnType"_L1] = QString::fromUtf8(normalizedType);
QJsonArray args;
for (const ArgumentDef &arg: arguments)
args.append(arg.toJson());
if (!args.isEmpty())
- fdef[QLatin1String("arguments")] = args;
+ fdef["arguments"_L1] = args;
accessToJson(&fdef, access);
if (revision > 0)
- fdef[QLatin1String("revision")] = revision;
+ fdef["revision"_L1] = revision;
+
+ if (wasCloned)
+ fdef["isCloned"_L1] = true;
return fdef;
}
@@ -2027,30 +2111,30 @@ QJsonObject FunctionDef::toJson() const
void FunctionDef::accessToJson(QJsonObject *obj, FunctionDef::Access acs)
{
switch (acs) {
- case Private: (*obj)[QLatin1String("access")] = QLatin1String("private"); break;
- case Public: (*obj)[QLatin1String("access")] = QLatin1String("public"); break;
- case Protected: (*obj)[QLatin1String("access")] = QLatin1String("protected"); break;
+ case Private: (*obj)["access"_L1] = "private"_L1; break;
+ case Public: (*obj)["access"_L1] = "public"_L1; break;
+ case Protected: (*obj)["access"_L1] = "protected"_L1; break;
}
}
QJsonObject ArgumentDef::toJson() const
{
QJsonObject arg;
- arg[QLatin1String("type")] = QString::fromUtf8(normalizedType);
+ arg["type"_L1] = QString::fromUtf8(normalizedType);
if (!name.isEmpty())
- arg[QLatin1String("name")] = QString::fromUtf8(name);
+ arg["name"_L1] = QString::fromUtf8(name);
return arg;
}
QJsonObject PropertyDef::toJson() const
{
QJsonObject prop;
- prop[QLatin1String("name")] = QString::fromUtf8(name);
- prop[QLatin1String("type")] = QString::fromUtf8(type);
+ prop["name"_L1] = QString::fromUtf8(name);
+ prop["type"_L1] = QString::fromUtf8(type);
const auto jsonify = [&prop](const char *str, const QByteArray &member) {
if (!member.isEmpty())
- prop[QLatin1String(str)] = QString::fromUtf8(member);
+ prop[QLatin1StringView(str)] = QString::fromUtf8(member);
};
jsonify("member", member);
@@ -2069,7 +2153,7 @@ QJsonObject PropertyDef::toJson() const
value = false;
else
value = QString::fromUtf8(boolOrString); // function name to query at run-time
- prop[QLatin1String(str)] = value;
+ prop[QLatin1StringView(str)] = value;
};
jsonifyBoolOrString("designable", designable);
@@ -2077,12 +2161,12 @@ QJsonObject PropertyDef::toJson() const
jsonifyBoolOrString("stored", stored);
jsonifyBoolOrString("user", user);
- prop[QLatin1String("constant")] = constant;
- prop[QLatin1String("final")] = final;
- prop[QLatin1String("required")] = required;
- prop[QLatin1String("index")] = relativeIndex;
+ prop["constant"_L1] = constant;
+ prop["final"_L1] = final;
+ prop["required"_L1] = required;
+ prop["index"_L1] = relativeIndex;
if (revision > 0)
- prop[QLatin1String("revision")] = revision;
+ prop["revision"_L1] = revision;
return prop;
}
@@ -2090,19 +2174,40 @@ QJsonObject PropertyDef::toJson() const
QJsonObject EnumDef::toJson(const ClassDef &cdef) const
{
QJsonObject def;
- def[QLatin1String("name")] = QString::fromUtf8(name);
+ def["name"_L1] = QString::fromUtf8(name);
if (!enumName.isEmpty())
- def[QLatin1String("alias")] = QString::fromUtf8(enumName);
- def[QLatin1String("isFlag")] = cdef.enumDeclarations.value(name);
- def[QLatin1String("isClass")] = isEnumClass;
+ def["alias"_L1] = QString::fromUtf8(enumName);
+ if (!type.isEmpty())
+ def["type"_L1] = QString::fromUtf8(type);
+ def["isFlag"_L1] = cdef.enumDeclarations.value(name);
+ def["isClass"_L1] = isEnumClass;
QJsonArray valueArr;
for (const QByteArray &value: values)
valueArr.append(QString::fromUtf8(value));
if (!valueArr.isEmpty())
- def[QLatin1String("values")] = valueArr;
+ def["values"_L1] = valueArr;
return def;
}
+QByteArray EnumDef::qualifiedType(const ClassDef *cdef) const
+{
+ if (name == cdef->classname) {
+ // The name of the enclosing namespace is the same as the enum class name
+ if (cdef->qualified.contains("::")) {
+ // QTBUG-112996, fully qualify by using cdef->qualified to disambiguate enum
+ // class name and enclosing namespace, e.g.:
+ // namespace A { namespace B { Q_NAMESPACE; enum class B { }; Q_ENUM_NS(B) } }
+ return cdef->qualified % "::" % name;
+ } else {
+ // Just "B"; otherwise the compiler complains about the type "B::B" inside
+ // "B::staticMetaObject" in the generated code; e.g.:
+ // namespace B { Q_NAMESPACE; enum class B { }; Q_ENUM_NS(B) }
+ return name;
+ }
+ }
+ return cdef->classname % "::" % name;
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 1c2d6624fa..c1759fb0a3 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef MOC_H
#define MOC_H
@@ -32,13 +7,13 @@
#include "parser.h"
#include <qstringlist.h>
#include <qmap.h>
-#include <qpair.h>
#include <qjsondocument.h>
#include <qjsonarray.h>
#include <qjsonobject.h>
-#include <qversionnumber.h>
+#include <qtyperevision.h>
#include <stdio.h>
-#include <ctype.h>
+
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
@@ -67,10 +42,12 @@ struct EnumDef
{
QByteArray name;
QByteArray enumName;
+ QByteArray type;
QList<QByteArray> values;
bool isEnumClass; // c++11 enum class
EnumDef() : isEnumClass(false) {}
QJsonObject toJson(const ClassDef &cdef) const;
+ QByteArray qualifiedType(const ClassDef *cdef) const;
};
Q_DECLARE_TYPEINFO(EnumDef, Q_RELOCATABLE_TYPE);
@@ -126,8 +103,10 @@ Q_DECLARE_TYPEINFO(FunctionDef, Q_RELOCATABLE_TYPE);
struct PropertyDef
{
bool stdCppSet() const {
+ if (name.isEmpty())
+ return false;
QByteArray s("set");
- s += toupper(name[0]);
+ s += QtMiscUtils::toAsciiUpper(name[0]);
s += name.mid(1);
return (s == write);
}
@@ -142,7 +121,7 @@ struct PropertyDef
bool required = false;
int relativeIndex = -1; // property index in current metaobject
- int location = -1; // token index, used for error reporting
+ qsizetype location = -1; // token index, used for error reporting
QJsonObject toJson() const;
};
@@ -172,12 +151,19 @@ struct BaseDef {
QMap<QByteArray, bool> enumDeclarations;
QList<EnumDef> enumList;
QMap<QByteArray, QByteArray> flagAliases;
- int begin = 0;
- int end = 0;
+ qsizetype begin = 0;
+ qsizetype end = 0;
+};
+
+struct SuperClass {
+ QByteArray classname;
+ QByteArray qualified;
+ FunctionDef::Access access;
};
+Q_DECLARE_TYPEINFO(SuperClass, Q_RELOCATABLE_TYPE);
struct ClassDef : BaseDef {
- QList<QPair<QByteArray, FunctionDef::Access>> superclassList;
+ QList<SuperClass> superclassList;
struct Interface
{
@@ -221,6 +207,8 @@ Q_DECLARE_TYPEINFO(NamespaceDef, Q_RELOCATABLE_TYPE);
class Moc : public Parser
{
public:
+ enum PropertyMode { Named, Anonymous };
+
Moc()
: noInclude(false), mustIncludeQPluginH(false), requireCompleteTypes(false)
{}
@@ -253,6 +241,10 @@ public:
return index > def->begin && index < def->end - 1;
}
+ const QByteArray &toFullyQualified(const QByteArray &name) const noexcept;
+
+ void prependNamespaces(BaseDef &def, const QList<NamespaceDef> &namespaceList) const;
+
Type parseType();
bool parseEnum(EnumDef *def);
@@ -262,9 +254,11 @@ public:
void parseSlots(ClassDef *def, FunctionDef::Access access);
void parseSignals(ClassDef *def);
- void parseProperty(ClassDef *def);
+ void parseProperty(ClassDef *def, PropertyMode mode);
void parsePluginData(ClassDef *def);
- void createPropertyDef(PropertyDef &def, int propertyIndex);
+
+ void createPropertyDef(PropertyDef &def, int propertyIndex, PropertyMode mode);
+
void parsePropertyAttributes(PropertyDef &propDef);
void parseEnumOrFlag(BaseDef *def, bool isFlag);
void parseFlag(BaseDef *def);
@@ -277,7 +271,7 @@ public:
void parseMocInclude();
void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
QByteArray parsePropertyAccessor();
- void parsePrivateProperty(ClassDef *def);
+ void parsePrivateProperty(ClassDef *def, PropertyMode mode);
void parseFunctionArguments(FunctionDef *def);
@@ -295,14 +289,17 @@ public:
void checkSuperClasses(ClassDef *def);
void checkProperties(ClassDef* cdef);
+ bool testForFunctionModifiers(FunctionDef *def);
+
+ void checkListSizes(const ClassDef &def);
};
inline QByteArray noRef(const QByteArray &type)
{
if (type.endsWith('&')) {
if (type.endsWith("&&"))
- return type.left(type.length()-2);
- return type.left(type.length()-1);
+ return type.left(type.size()-2);
+ return type.left(type.size()-1);
}
return type;
}
diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h
index e8d2d1b1b9..3bc5a872ed 100644
--- a/src/tools/moc/outputrevision.h
+++ b/src/tools/moc/outputrevision.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef OUTPUTREVISION_H
#define OUTPUTREVISION_H
diff --git a/src/tools/moc/parser.cpp b/src/tools/moc/parser.cpp
index 4b67e3a99a..1cfb8ce486 100644
--- a/src/tools/moc/parser.cpp
+++ b/src/tools/moc/parser.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "parser.h"
#include "utils.h"
@@ -33,42 +8,80 @@
QT_BEGIN_NAMESPACE
-#ifdef USE_LEXEM_STORE
-Symbol::LexemStore Symbol::lexemStore;
-#endif
-
static const char *error_msg = nullptr;
+/*! \internal
+ Base implementation for printing diagnostic messages.
+
+ For example:
+ "/path/to/file:line:column: error: %s\n"
+ '%s' is replaced by \a msg. (Currently "column" is always 1).
+
+ If sym.lineNum is -1, the line and column parts aren't printed:
+ "/path/to/file: error: %s\n"
+
+ \a formatStringSuffix specifies the type of the message e.g.:
+ "error: %s\n"
+ "warning: %s\n"
+ "note: %s\n"
+ "Parse error at %s\n" (from defaultErrorMsg())
+*/
+void Parser::printMsg(QByteArrayView formatStringSuffix, QByteArrayView msg, const Symbol &sym)
+{
+ if (sym.lineNum != -1) {
#ifdef Q_CC_MSVC
-#define ErrorFormatString "%s(%d:%d): "
+ QByteArray formatString = "%s(%d:%d): " + formatStringSuffix;
#else
-#define ErrorFormatString "%s:%d:%d: "
+ QByteArray formatString = "%s:%d:%d: " + formatStringSuffix;
#endif
+ fprintf(stderr, formatString.constData(),
+ currentFilenames.top().constData(), sym.lineNum, 1, msg.data());
+ } else {
+ QByteArray formatString = "%s: " + formatStringSuffix;
+ fprintf(stderr, formatString.constData(),
+ currentFilenames.top().constData(), msg.data());
+ }
+}
+
+void Parser::defaultErrorMsg(const Symbol &sym)
+{
+ if (sym.lineNum != -1)
+ printMsg("error: Parse error at \"%s\"\n", sym.lexem().data(), sym);
+ else
+ printMsg("error: could not parse file\n", "", sym);
+}
-void Parser::error(int rollback) {
- index -= rollback;
- error();
+void Parser::error(const Symbol &sym)
+{
+ defaultErrorMsg(sym);
+ exit(EXIT_FAILURE);
}
-void Parser::error(const char *msg) {
+
+void Parser::error(const char *msg)
+{
if (msg || error_msg)
- fprintf(stderr, ErrorFormatString "error: %s\n",
- currentFilenames.top().constData(), symbol().lineNum, 1, msg?msg:error_msg);
+ printMsg("error: %s\n",
+ msg ? msg : error_msg,
+ index > 0 ? symbol() : Symbol{});
else
- fprintf(stderr, ErrorFormatString "error: Parse error at \"%s\"\n",
- currentFilenames.top().constData(), symbol().lineNum, 1, symbol().lexem().data());
+ defaultErrorMsg(symbol());
+
exit(EXIT_FAILURE);
}
+void Parser::warning(const Symbol &sym, QByteArrayView msg)
+{
+ if (displayWarnings)
+ printMsg("warning: %s\n", msg, sym);
+}
+
void Parser::warning(const char *msg) {
- if (displayWarnings && msg)
- fprintf(stderr, ErrorFormatString "warning: %s\n",
- currentFilenames.top().constData(), qMax(0, index > 0 ? symbol().lineNum : 0), 1, msg);
+ warning(index > 0 ? symbol() : Symbol{}, msg);
}
void Parser::note(const char *msg) {
if (displayNotes && msg)
- fprintf(stderr, ErrorFormatString "note: %s\n",
- currentFilenames.top().constData(), qMax(0, index > 0 ? symbol().lineNum : 0), 1, msg);
+ printMsg("note: %s\n", msg, index > 0 ? symbol() : Symbol{});
}
QT_END_NAMESPACE
diff --git a/src/tools/moc/parser.h b/src/tools/moc/parser.h
index f014d7e6b5..6fe982a1ce 100644
--- a/src/tools/moc/parser.h
+++ b/src/tools/moc/parser.h
@@ -1,35 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PARSER_H
#define PARSER_H
#include "symbols.h"
+#include <QtCore/qbytearrayview.h>
#include <stack>
@@ -40,7 +16,7 @@ class Parser
public:
Parser():index(0), displayWarnings(true), displayNotes(true) {}
Symbols symbols;
- int index;
+ qsizetype index;
bool displayWarnings;
bool displayNotes;
@@ -68,11 +44,15 @@ public:
inline QByteArray lexem() { return symbols.at(index-1).lexem();}
inline QByteArray unquotedLexem() { return symbols.at(index-1).unquotedLexem();}
inline const Symbol &symbol() { return symbols.at(index-1);}
+ inline const Symbol &symbolAt(qsizetype idx) { return symbols.at(idx); }
- Q_NORETURN void error(int rollback);
+ Q_NORETURN void error(const Symbol &symbol);
Q_NORETURN void error(const char *msg = nullptr);
void warning(const char * = nullptr);
+ void warning(const Symbol &sym, QByteArrayView msg);
void note(const char * = nullptr);
+ void defaultErrorMsg(const Symbol &sym);
+ void printMsg(QByteArrayView formatStringSuffix, QByteArrayView msg, const Symbol &sym);
};
@@ -87,7 +67,7 @@ inline bool Parser::test(Token token)
inline Token Parser::lookup(int k)
{
- const int l = index - 1 + k;
+ const qsizetype l = index - 1 + k;
return l < symbols.size() ? symbols.at(l).token : NOTOKEN;
}
diff --git a/src/tools/moc/ppkeywords.cpp b/src/tools/moc/ppkeywords.cpp
index b94abf8cd8..dc13f3db95 100644
--- a/src/tools/moc/ppkeywords.cpp
+++ b/src/tools/moc/ppkeywords.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// auto generated
// DO NOT EDIT.
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index c6e84c0913..11ea8d417e 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.org>
-** 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 The Qt Company Ltd.
+// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "preprocessor.h"
#include "utils.h"
@@ -33,9 +8,12 @@
#include <qfile.h>
#include <qdir.h>
#include <qfileinfo.h>
+#include <qvarlengtharray.h>
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
#include "ppkeywords.cpp"
#include "keywords.cpp"
@@ -236,7 +214,9 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
data -= 2;
break;
case DIGIT:
- while (is_digit_char(*data) || *data == '\'')
+ {
+ bool hasSeenTokenSeparator = false;;
+ while (isAsciiDigit(*data) || (hasSeenTokenSeparator = *data == '\''))
++data;
if (!*data || *data != '.') {
token = INTEGER_LITERAL;
@@ -245,22 +225,30 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
|| *data == 'b' || *data == 'B')
&& *lexem == '0') {
++data;
- while (is_hex_char(*data) || *data == '\'')
+ while (isHexDigit(*data) || (hasSeenTokenSeparator = *data == '\''))
+ ++data;
+ } else if (*data == 'L') // TODO: handle other suffixes
+ ++data;
+ if (!hasSeenTokenSeparator) {
+ while (is_ident_char(*data)) {
++data;
+ token = IDENTIFIER;
+ }
}
break;
}
token = FLOATING_LITERAL;
++data;
Q_FALLTHROUGH();
+ }
case FLOATING_LITERAL:
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
if (*data == '+' || *data == '-')
++data;
if (*data == 'e' || *data == 'E') {
++data;
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
}
if (*data == 'f' || *data == 'F'
@@ -339,16 +327,7 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
continue; //ignore
}
}
-#ifdef USE_LEXEM_STORE
- if (!Preprocessor::preprocessOnly
- && token != IDENTIFIER
- && token != STRING_LITERAL
- && token != FLOATING_LITERAL
- && token != INTEGER_LITERAL)
- symbols += Symbol(lineNum, token);
- else
-#endif
- symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
+ symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
} else { // Preprocessor
@@ -414,7 +393,7 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
token = PP_CHARACTER_LITERAL;
break;
case PP_DIGIT:
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
if (!*data || *data != '.') {
token = PP_INTEGER_LITERAL;
@@ -422,22 +401,23 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
(*data == 'x' || *data == 'X')
&& *lexem == '0') {
++data;
- while (is_hex_char(*data) || *data == '\'')
+ while (isHexDigit(*data) || *data == '\'')
++data;
- }
+ } else if (*data == 'L') // TODO: handle other suffixes
+ ++data;
break;
}
token = PP_FLOATING_LITERAL;
++data;
Q_FALLTHROUGH();
case PP_FLOATING_LITERAL:
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
if (*data == '+' || *data == '-')
++data;
if (*data == 'e' || *data == 'E') {
++data;
- while (is_digit_char(*data) || *data == '\'')
+ while (isAsciiDigit(*data) || *data == '\'')
++data;
}
if (*data == 'f' || *data == 'F'
@@ -519,22 +499,14 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
}
if (mode == PreparePreprocessorStatement)
continue;
-#ifdef USE_LEXEM_STORE
- if (token != PP_IDENTIFIER
- && token != PP_STRING_LITERAL
- && token != PP_FLOATING_LITERAL
- && token != PP_INTEGER_LITERAL)
- symbols += Symbol(lineNum, token);
- else
-#endif
- symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
+ symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
}
}
symbols += Symbol(); // eof symbol
return symbols;
}
-void Preprocessor::macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand, int &index,
+void Preprocessor::macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand, qsizetype &index,
int lineNum, bool one, const QSet<QByteArray> &excludeSymbols)
{
SymbolStack symbols;
@@ -642,19 +614,22 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
HashHash
} mode = Normal;
- for (int i = 0; i < macro.symbols.size(); ++i) {
- const Symbol &s = macro.symbols.at(i);
+ const auto end = macro.symbols.cend();
+ auto it = macro.symbols.cbegin();
+ const auto lastSym = std::prev(macro.symbols.cend(), !macro.symbols.isEmpty() ? 1 : 0);
+ for (; it != end; ++it) {
+ const Symbol &s = *it;
if (s.token == HASH || s.token == PP_HASHHASH) {
mode = (s.token == HASH ? Hash : HashHash);
continue;
}
- int index = macro.arguments.indexOf(s);
+ const qsizetype index = macro.arguments.indexOf(s);
if (mode == Normal) {
if (index >= 0 && index < arguments.size()) {
// each argument undoergoes macro expansion if it's not used as part of a # or ##
- if (i == macro.symbols.size() - 1 || macro.symbols.at(i + 1).token != PP_HASHHASH) {
+ if (it == lastSym || std::next(it)->token != PP_HASHHASH) {
Symbols arg = arguments.at(index);
- int idx = 1;
+ qsizetype idx = 1;
macroExpand(&expansion, that, arg, idx, lineNum, false, symbols.excludeSymbols());
} else {
expansion += arguments.at(index);
@@ -673,9 +648,9 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
const Symbols &arg = arguments.at(index);
QByteArray stringified;
- for (int i = 0; i < arg.size(); ++i) {
- stringified += arg.at(i).lexem();
- }
+ for (const Symbol &sym : arg)
+ stringified += sym.lexem();
+
stringified.replace('"', "\\\"");
stringified.prepend('"');
stringified.append('"');
@@ -709,8 +684,8 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
if (index >= 0 && index < arguments.size()) {
const Symbols &arg = arguments.at(index);
- for (int i = 1; i < arg.size(); ++i)
- expansion += arg.at(i);
+ if (!arg.isEmpty())
+ expansion.append(arg.cbegin() + 1, arg.cend());
}
}
mode = Normal;
@@ -951,7 +926,11 @@ int PP_Expression::primary_expression()
test(PP_RPAREN);
} else {
next();
- value = lexem().toInt(nullptr, 0);
+ const QByteArray &lex = lexem();
+ auto lexView = QByteArrayView(lex);
+ if (lex.endsWith('L'))
+ lexView.chop(1);
+ value = lexView.toInt(nullptr, 0);
}
return value;
}
@@ -990,7 +969,7 @@ static void mergeStringLiterals(Symbols *_symbols)
for (Symbols::iterator i = symbols.begin(); i != symbols.end(); ++i) {
if (i->token == STRING_LITERAL) {
Symbols::Iterator mergeSymbol = i;
- int literalsLength = mergeSymbol->len;
+ qsizetype literalsLength = mergeSymbol->len;
while (++i != symbols.end() && i->token == STRING_LITERAL)
literalsLength += i->len - 2; // no quotes
@@ -1004,7 +983,7 @@ static void mergeStringLiterals(Symbols *_symbols)
for (Symbols::iterator j = mergeSymbol + 1; j != i; ++j)
mergeSymbolLexem.append(j->lex.constData() + j->from + 1, j->len - 2); // append j->unquotedLexem()
mergeSymbolLexem.append('"');
- mergeSymbol->len = mergeSymbol->lex.length();
+ mergeSymbol->len = mergeSymbol->lex.size();
mergeSymbol->from = 0;
i = symbols.erase(mergeSymbol + 1, i);
}
@@ -1015,13 +994,21 @@ static void mergeStringLiterals(Symbols *_symbols)
}
static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepaths,
- const QByteArray &include)
+ const QByteArray &include,
+ const bool debugIncludes)
{
QFileInfo fi;
- for (int j = 0; j < includepaths.size() && !fi.exists(); ++j) {
- const Parser::IncludePath &p = includepaths.at(j);
+
+ if (Q_UNLIKELY(debugIncludes)) {
+ fprintf(stderr, "debug-includes: searching for '%s'\n", include.constData());
+ }
+
+ for (const Parser::IncludePath &p : includepaths) {
+ if (fi.exists())
+ break;
+
if (p.isFrameworkPath) {
- const int slashPos = include.indexOf('/');
+ const qsizetype slashPos = include.indexOf('/');
if (slashPos == -1)
continue;
fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
@@ -1029,6 +1016,12 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
} else {
fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include));
}
+
+ if (Q_UNLIKELY(debugIncludes)) {
+ const auto candidate = fi.filePath().toLocal8Bit();
+ fprintf(stderr, "debug-includes: considering '%s'\n", candidate.constData());
+ }
+
// try again, maybe there's a file later in the include paths with the same name
// (186067)
if (fi.isDir()) {
@@ -1037,9 +1030,20 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
}
}
- if (!fi.exists() || fi.isDir())
+ if (!fi.exists() || fi.isDir()) {
+ if (Q_UNLIKELY(debugIncludes)) {
+ fprintf(stderr, "debug-includes: can't find '%s'\n", include.constData());
+ }
return QByteArray();
- return fi.canonicalFilePath().toLocal8Bit();
+ }
+
+ const auto result = fi.canonicalFilePath().toLocal8Bit();
+
+ if (Q_UNLIKELY(debugIncludes)) {
+ fprintf(stderr, "debug-includes: found '%s'\n", result.constData());
+ }
+
+ return result;
}
QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
@@ -1053,7 +1057,11 @@ QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteAr
auto it = nonlocalIncludePathResolutionCache.find(include);
if (it == nonlocalIncludePathResolutionCache.end())
- it = nonlocalIncludePathResolutionCache.insert(include, searchIncludePaths(includes, include));
+ it = nonlocalIncludePathResolutionCache.insert(include,
+ searchIncludePaths(
+ includes,
+ include,
+ debugIncludes));
return it.value();
}
@@ -1096,7 +1104,7 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
continue;
Symbols saveSymbols = symbols;
- int saveIndex = index;
+ qsizetype saveIndex = index;
// phase 1: get rid of backslash-newlines
input = cleaned(input);
@@ -1131,14 +1139,14 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
} else {
macro.isFunction = false;
}
- int start = index;
+ qsizetype start = index;
until(PP_NEWLINE);
macro.symbols.reserve(index - start - 1);
// remove whitespace where there shouldn't be any:
// Before and after the macro, after a # and around ##
Token lastToken = HASH; // skip shitespace at the beginning
- for (int i = start; i < index - 1; ++i) {
+ for (qsizetype i = start; i < index - 1; ++i) {
Token token = symbols.at(i).token;
if (token == WHITESPACE) {
if (lastToken == PP_HASH || lastToken == HASH ||
@@ -1281,7 +1289,7 @@ void Preprocessor::parseDefineArguments(Macro *m)
if (!test(PP_RPAREN))
error("missing ')' in macro argument list");
break;
- } else if (!is_identifier(l.constData(), l.length())) {
+ } else if (!is_identifier(l.constData(), l.size())) {
error("Unexpected character in macro argument list.");
}
}
@@ -1318,4 +1326,10 @@ void Preprocessor::until(Token t)
;
}
+void Preprocessor::setDebugIncludes(bool value)
+{
+ debugIncludes = value;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index 39f56d6e92..3509e83dce 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PREPROCESSOR_H
#define PREPROCESSOR_H
@@ -45,11 +20,7 @@ struct Macro
Symbols symbols;
};
-#ifdef USE_LEXEM_STORE
-typedef QByteArray MacroName;
-#else
typedef SubArray MacroName;
-#endif
typedef QHash<MacroName, Macro> Macros;
class QFile;
@@ -73,18 +44,22 @@ public:
void substituteUntilNewline(Symbols &substituted);
static Symbols macroExpandIdentifier(Preprocessor *that, SymbolStack &symbols, int lineNum, QByteArray *macroName);
- static void macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand, int &index, int lineNum, bool one,
- const QSet<QByteArray> &excludeSymbols = QSet<QByteArray>());
+ static void macroExpand(Symbols *into, Preprocessor *that, const Symbols &toExpand,
+ qsizetype &index, int lineNum, bool one,
+ const QSet<QByteArray> &excludeSymbols = QSet<QByteArray>());
int evaluateCondition();
enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude, PrepareDefine, TokenizeDefine };
static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp);
+ void setDebugIncludes(bool value);
+
private:
void until(Token);
void preprocess(const QByteArray &filename, Symbols &preprocessed);
+ bool debugIncludes = false;
};
QT_END_NAMESPACE
diff --git a/src/tools/moc/symbols.h b/src/tools/moc/symbols.h
index bbb1312cdc..869f7c793f 100644
--- a/src/tools/moc/symbols.h
+++ b/src/tools/moc/symbols.h
@@ -1,111 +1,62 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
-** 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 The Qt Company Ltd.
+// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef SYMBOLS_H
#define SYMBOLS_H
#include "token.h"
#include <qdebug.h>
-#include <qhash.h>
+#include <qhashfunctions.h>
#include <qlist.h>
#include <qstack.h>
#include <qstring.h>
+#include <qset.h>
QT_BEGIN_NAMESPACE
-//#define USE_LEXEM_STORE
-
struct SubArray
{
- inline SubArray():from(0),len(-1){}
+ inline SubArray() = default;
inline SubArray(const QByteArray &a):array(a),from(0), len(a.size()){}
inline SubArray(const char *s):array(s),from(0) { len = array.size(); }
- inline SubArray(const QByteArray &a, int from, int len):array(a), from(from), len(len){}
+ SubArray(const QByteArray &a, qsizetype from, qsizetype len)
+ : array(a), from(from), len(len)
+ {
+ }
QByteArray array;
- int from, len;
+ qsizetype from = 0;
+ qsizetype len = -1;
inline bool operator==(const SubArray &other) const {
if (len != other.len)
return false;
- for (int i = 0; i < len; ++i)
- if (array.at(from + i) != other.array.at(other.from + i))
- return false;
- return true;
+ const auto begin = array.cbegin() + from;
+ const auto end = begin + len;
+ const auto other_begin = other.array.cbegin() + other.from;
+ return std::equal(begin, end, other_begin);
}
};
-inline size_t qHash(const SubArray &key)
+inline size_t qHash(const SubArray &key, size_t seed = 0)
{
- return qHash(QLatin1String(key.array.constData() + key.from, key.len));
+ return qHash(QLatin1StringView(key.array.constData() + key.from, key.len), seed);
}
struct Symbol
{
-
-#ifdef USE_LEXEM_STORE
- typedef QHash<SubArray, QHashDummyValue> LexemStore;
- static LexemStore lexemStore;
-
- inline Symbol() : lineNum(-1),token(NOTOKEN){}
- inline Symbol(int lineNum, Token token):
- lineNum(lineNum), token(token){}
- inline Symbol(int lineNum, Token token, const QByteArray &lexem):
- lineNum(lineNum), token(token),lex(lexem){}
- inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len):
- lineNum(lineNum), token(token){
- LexemStore::const_iterator it = lexemStore.constFind(SubArray(lexem, from, len));
-
- if (it != lexemStore.constEnd()) {
- lex = it.key().array;
- } else {
- lex = lexem.mid(from, len);
- lexemStore.insert(lex, QHashDummyValue());
- }
+ inline Symbol() = default;
+ inline Symbol(int lineNum, Token token) : lineNum(lineNum), token(token) { }
+ inline Symbol(int lineNum, Token token, const QByteArray &lexem)
+ : lineNum(lineNum), token(token), lex(lexem), len(lex.size())
+ {
}
- int lineNum;
- Token token;
- inline QByteArray unquotedLexem() const { return lex.mid(1, lex.length()-2); }
- inline QByteArray lexem() const { return lex; }
- inline operator QByteArray() const { return lex; }
- QByteArray lex;
-
-#else
-
- inline Symbol() : lineNum(-1),token(NOTOKEN), from(0),len(-1) {}
- inline Symbol(int lineNum, Token token):
- lineNum(lineNum), token(token), from(0), len(-1) {}
- inline Symbol(int lineNum, Token token, const QByteArray &lexem):
- lineNum(lineNum), token(token), lex(lexem), from(0) { len = lex.size(); }
- inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len):
- lineNum(lineNum), token(token),lex(lexem),from(from), len(len){}
- int lineNum;
- Token token;
+ Symbol(int lineNum, Token token, const QByteArray &lexem, qsizetype from, qsizetype len)
+ : lineNum(lineNum), token(token), lex(lexem), from(from), len(len)
+ {
+ }
+ int lineNum = -1;
+ Token token = NOTOKEN;
inline QByteArray lexem() const { return lex.mid(from, len); }
inline QByteArray unquotedLexem() const { return lex.mid(from+1, len-2); }
inline operator SubArray() const { return SubArray(lex, from, len); }
@@ -114,9 +65,8 @@ struct Symbol
return SubArray(lex, from, len) == SubArray(o.lex, o.from, o.len);
}
QByteArray lex;
- int from, len;
-
-#endif
+ qsizetype from = 0;
+ qsizetype len = -1;
};
Q_DECLARE_TYPEINFO(Symbol, Q_RELOCATABLE_TYPE);
@@ -126,7 +76,7 @@ struct SafeSymbols {
Symbols symbols;
QByteArray expandedMacro;
QSet<QByteArray> excludedSymbols;
- int index;
+ qsizetype index;
};
Q_DECLARE_TYPEINFO(SafeSymbols, Q_RELOCATABLE_TYPE);
@@ -151,13 +101,13 @@ public:
inline QByteArray lexem() const { return symbol().lexem(); }
inline QByteArray unquotedLexem() { return symbol().unquotedLexem(); }
- bool dontReplaceSymbol(const QByteArray &name);
- QSet<QByteArray> excludeSymbols();
+ bool dontReplaceSymbol(const QByteArray &name) const;
+ QSet<QByteArray> excludeSymbols() const;
};
inline bool SymbolStack::test(Token token)
{
- int stackPos = size() - 1;
+ qsizetype stackPos = size() - 1;
while (stackPos >= 0 && at(stackPos).index >= at(stackPos).symbols.size())
--stackPos;
if (stackPos < 0)
@@ -169,21 +119,20 @@ inline bool SymbolStack::test(Token token)
return false;
}
-inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name)
+inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name) const
{
- for (int i = 0; i < size(); ++i) {
- if (name == at(i).expandedMacro || at(i).excludedSymbols.contains(name))
- return true;
- }
- return false;
+ auto matchesName = [&name](const SafeSymbols &sf) {
+ return name == sf.expandedMacro || sf.excludedSymbols.contains(name);
+ };
+ return std::any_of(cbegin(), cend(), matchesName);
}
-inline QSet<QByteArray> SymbolStack::excludeSymbols()
+inline QSet<QByteArray> SymbolStack::excludeSymbols() const
{
QSet<QByteArray> set;
- for (int i = 0; i < size(); ++i) {
- set << at(i).expandedMacro;
- set += at(i).excludedSymbols;
+ for (const SafeSymbols &sf : *this) {
+ set << sf.expandedMacro;
+ set += sf.excludedSymbols;
}
return set;
}
diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp
index cf1aa102c7..bfefaff57b 100644
--- a/src/tools/moc/token.cpp
+++ b/src/tools/moc/token.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "token.h"
diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h
index e9696aaea2..a70808370d 100644
--- a/src/tools/moc/token.h
+++ b/src/tools/moc/token.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef TOKEN_H
#define TOKEN_H
@@ -158,6 +133,7 @@ QT_BEGIN_NAMESPACE
F(Q_NAMESPACE_TOKEN) \
F(Q_NAMESPACE_EXPORT_TOKEN) \
F(Q_PROPERTY_TOKEN) \
+ F(QT_ANONYMOUS_PROPERTY_TOKEN) \
F(Q_PLUGIN_METADATA_TOKEN) \
F(Q_ENUMS_TOKEN) \
F(Q_ENUM_TOKEN) \
@@ -179,6 +155,7 @@ QT_BEGIN_NAMESPACE
F(Q_INVOKABLE_TOKEN) \
F(Q_SCRIPTABLE_TOKEN) \
F(Q_PRIVATE_PROPERTY_TOKEN) \
+ F(QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN) \
F(Q_REVISION_TOKEN) \
F(Q_MOC_INCLUDE_TOKEN) \
F(SPECIAL_TREATMENT_MARK) \
diff --git a/src/tools/moc/util/generate.sh b/src/tools/moc/util/generate.sh
index 5460d28924..6be06e5a91 100755
--- a/src/tools/moc/util/generate.sh
+++ b/src/tools/moc/util/generate.sh
@@ -1,37 +1,12 @@
#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility 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 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
set -ex
qmake
make
-cat licenseheader.txt > ../keywords.cpp
-cat licenseheader.txt > ../ppkeywords.cpp
+cat licenseheader.cpp.in > ../keywords.cpp
+cat licenseheader.cpp.in > ../ppkeywords.cpp
./generate_keywords >> ../keywords.cpp
./generate_keywords preprocessor >> ../ppkeywords.cpp
diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp
index 3ee46ca114..a6c85af9f1 100644
--- a/src/tools/moc/util/generate_keywords.cpp
+++ b/src/tools/moc/util/generate_keywords.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <stdio.h>
#include <string.h>
#include <qbytearray.h>
@@ -218,6 +193,7 @@ static const Keyword keywords[] = {
{ "Q_GADGET", "Q_GADGET_TOKEN" },
{ "Q_GADGET_EXPORT", "Q_GADGET_EXPORT_TOKEN" },
{ "Q_PROPERTY", "Q_PROPERTY_TOKEN" },
+ { "QT_ANONYMOUS_PROPERTY", "QT_ANONYMOUS_PROPERTY_TOKEN" },
{ "Q_PLUGIN_METADATA", "Q_PLUGIN_METADATA_TOKEN" },
{ "Q_ENUMS", "Q_ENUMS_TOKEN" },
{ "Q_ENUM", "Q_ENUM_TOKEN" },
@@ -243,6 +219,7 @@ static const Keyword keywords[] = {
{ "Q_SLOT", "Q_SLOT_TOKEN" },
{ "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" },
{ "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" },
+ { "QT_ANONYMOUS_PRIVATE_PROPERTY", "QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN" },
{ "Q_REVISION", "Q_REVISION_TOKEN" },
{ "Q_MOC_INCLUDE", "Q_MOC_INCLUDE_TOKEN" },
{ "\n", "NEWLINE" },
diff --git a/src/tools/moc/util/licenseheader.cpp.in b/src/tools/moc/util/licenseheader.cpp.in
new file mode 100644
index 0000000000..42958a66f5
--- /dev/null
+++ b/src/tools/moc/util/licenseheader.cpp.in
@@ -0,0 +1,3 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
diff --git a/src/tools/moc/util/licenseheader.txt b/src/tools/moc/util/licenseheader.txt
deleted file mode 100644
index b2b02f82eb..0000000000
--- a/src/tools/moc/util/licenseheader.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
-
diff --git a/src/tools/moc/utils.h b/src/tools/moc/utils.h
index 4cb1d90345..0b0d70f462 100644
--- a/src/tools/moc/utils.h
+++ b/src/tools/moc/utils.h
@@ -1,35 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef UTILS_H
#define UTILS_H
#include <QtCore/qglobal.h>
+#include <private/qtools_p.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -45,49 +23,20 @@ inline bool is_space(char s)
inline bool is_ident_start(char s)
{
- return ((s >= 'a' && s <= 'z')
- || (s >= 'A' && s <= 'Z')
- || s == '_' || s == '$'
- );
+ using namespace QtMiscUtils;
+ return isAsciiLower(s) || isAsciiUpper(s) || s == '_' || s == '$';
}
inline bool is_ident_char(char s)
{
- return ((s >= 'a' && s <= 'z')
- || (s >= 'A' && s <= 'Z')
- || (s >= '0' && s <= '9')
- || s == '_' || s == '$'
- );
+ return QtMiscUtils::isAsciiLetterOrNumber(s) || s == '_' || s == '$';
}
-inline bool is_identifier(const char *s, int len)
+inline bool is_identifier(const char *s, qsizetype len)
{
if (len < 1)
return false;
- if (!is_ident_start(*s))
- return false;
- for (int i = 1; i < len; ++i)
- if (!is_ident_char(s[i]))
- return false;
- return true;
-}
-
-inline bool is_digit_char(char s)
-{
- return (s >= '0' && s <= '9');
-}
-
-inline bool is_octal_char(char s)
-{
- return (s >= '0' && s <= '7');
-}
-
-inline bool is_hex_char(char s)
-{
- return ((s >= 'a' && s <= 'f')
- || (s >= 'A' && s <= 'F')
- || (s >= '0' && s <= '9')
- );
+ return std::all_of(s, s + len, is_ident_char);
}
inline const char *skipQuote(const char *data)
diff --git a/src/tools/qdbuscpp2xml/CMakeLists.txt b/src/tools/qdbuscpp2xml/CMakeLists.txt
index eba1dad884..781c1835bc 100644
--- a/src/tools/qdbuscpp2xml/CMakeLists.txt
+++ b/src/tools/qdbuscpp2xml/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from qdbuscpp2xml.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## qdbuscpp2xml Tool:
@@ -6,8 +7,10 @@
qt_get_tool_target_name(target_name qdbuscpp2xml)
qt_internal_add_tool(${target_name}
+ TRY_RUN
+ TRY_RUN_FLAGS "-V"
TARGET_DESCRIPTION "Qt D-Bus C++ to XML Compiler"
- TOOLS_TARGET DBus # special case
+ TOOLS_TARGET DBus
SOURCES
../moc/cbordevice.h
../moc/collectjson.cpp ../moc/collectjson.h
@@ -26,25 +29,8 @@ qt_internal_add_tool(${target_name}
INCLUDE_DIRECTORIES
../moc
../moc/../../3rdparty/tinycbor/src
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::CorePrivate
Qt::DBusPrivate
- # COMPILE_OPTIONS # special case
- # "$$QT_HOST_CFLAGS_DBUS"
- # QMAKE_TARGET_DESCRIPTION = "Qt D-Bus C++ to XML Compiler"
- # _LOADED = "qt_tool"
- # _OPTION = "host_build"
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:qdbuscpp2xml.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt D-Bus C++ to XML Compiler"
-# _OPTION = "host_build"
-
-## Scopes:
-#####################################################################
-
-# special case begin
-# qt_internal_extend_target(qdbuscpp2xml CONDITION force_bootstrap [...])
-# qt_internal_extend_target(qdbuscpp2xml CONDITION NOT force_bootstrap [...])
-# special case end
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index 554ab0119e..3b7d73894b 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <qbuffer.h>
#include <qbytearray.h>
@@ -40,6 +15,9 @@
#include <qdbusconnection.h> // for the Export* flags
#include <private/qdbusconnection_p.h> // for the qDBusCheckAsyncTag
+#include <private/qdbusmetatype_p.h> // for QDBusMetaTypeId::init()
+
+using namespace Qt::StringLiterals;
// copied from dbus-protocol.h:
static const char docTypeHeader[] =
@@ -60,7 +38,7 @@ static const char docTypeHeader[] =
#define PROGRAMNAME "qdbuscpp2xml"
#define PROGRAMVERSION "0.2"
-#define PROGRAMCOPYRIGHT "Copyright (C) 2022 The Qt Company Ltd."
+#define PROGRAMCOPYRIGHT QT_COPYRIGHT
static QString outputFile;
static int flags;
@@ -95,7 +73,7 @@ int qDBusParametersForMethod(const FunctionDef &mm, QList<QMetaType> &metaTypes,
static inline QString typeNameToXml(const char *typeName)
{
- QString plain = QLatin1String(typeName);
+ QString plain = QLatin1StringView(typeName);
return plain.toHtmlEscaped();
}
@@ -133,13 +111,13 @@ static QString addFunction(const FunctionDef &mm, bool isSignal = false) {
qWarning() << qPrintable(errorMsg);
return QString(); // invalid form
}
- if (isSignal && inputCount + 1 != types.count())
+ if (isSignal && inputCount + 1 != types.size())
return QString(); // signal with output arguments?
if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message())
return QString(); // signal with QDBusMessage argument?
bool isScriptable = mm.isScriptable;
- for (int j = 1; j < types.count(); ++j) {
+ for (qsizetype j = 1; j < types.size(); ++j) {
// input parameter for a slot or output for a signal
if (types.at(j) == QDBusMetaTypeId::message()) {
isScriptable = true;
@@ -155,14 +133,14 @@ static QString addFunction(const FunctionDef &mm, bool isSignal = false) {
const char *signature = QDBusMetaType::typeToSignature(QMetaType(types.at(j)));
xml += QString::fromLatin1(" <arg %1type=\"%2\" direction=\"%3\"/>\n")
.arg(name,
- QLatin1String(signature),
- isOutput ? QLatin1String("out") : QLatin1String("in"));
+ QLatin1StringView(signature),
+ isOutput ? "out"_L1 : "in"_L1);
// do we need to describe this argument?
if (!QDBusMetaType::signatureToMetaType(signature).isValid()) {
const char *typeName = QMetaType(types.at(j)).name();
xml += QString::fromLatin1(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.%1%2\" value=\"%3\"/>\n")
- .arg(isOutput ? QLatin1String("Out") : QLatin1String("In"))
+ .arg(isOutput ? "Out"_L1 : "In"_L1)
.arg(isOutput && !isSignal ? j - inputCount : j - 1)
.arg(typeNameToXml(typeName));
}
@@ -180,12 +158,10 @@ static QString addFunction(const FunctionDef &mm, bool isSignal = false) {
if (qDBusCheckAsyncTag(mm.tag.constData()))
// add the no-reply annotation
- xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\""
- " value=\"true\"/>\n");
+ xml += " <annotation name=\"" ANNOTATION_NO_WAIT "\" value=\"true\"/>\n"_L1;
QString retval = xml;
- retval += QString::fromLatin1(" </%1>\n")
- .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
+ retval += QString::fromLatin1(" </%1>\n").arg(isSignal ? "signal"_L1 : "method"_L1);
return retval;
}
@@ -209,6 +185,8 @@ static QString generateInterfaceXml(const ClassDef *mo)
access |= 1;
if (!mp.write.isEmpty())
access |= 2;
+ if (!mp.member.isEmpty())
+ access |= 3;
int typeId = QMetaType::fromName(mp.type).id();
if (!typeId) {
@@ -221,15 +199,15 @@ static QString generateInterfaceXml(const ClassDef *mo)
continue;
retval += QString::fromLatin1(" <property name=\"%1\" type=\"%2\" access=\"%3\"")
- .arg(QLatin1String(mp.name),
- QLatin1String(signature),
- QLatin1String(accessvalues[access]));
+ .arg(QLatin1StringView(mp.name),
+ QLatin1StringView(signature),
+ QLatin1StringView(accessvalues[access]));
if (!QDBusMetaType::signatureToMetaType(signature).isValid()) {
retval += QString::fromLatin1(">\n <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n")
.arg(typeNameToXml(mp.type.constData()));
} else {
- retval += QLatin1String("/>\n");
+ retval += "/>\n"_L1;
}
}
}
@@ -272,17 +250,17 @@ QString qDBusInterfaceFromClassDef(const ClassDef *mo)
if (cid.name == QCLASSINFO_DBUS_INTERFACE)
return QString::fromUtf8(cid.value);
}
- interface = QLatin1String(mo->classname);
- interface.replace(QLatin1String("::"), QLatin1String("."));
+ interface = QLatin1StringView(mo->classname);
+ interface.replace("::"_L1, "."_L1);
- if (interface.startsWith(QLatin1String("QDBus"))) {
- interface.prepend(QLatin1String("org.qtproject.QtDBus."));
- } else if (interface.startsWith(QLatin1Char('Q')) &&
- interface.length() >= 2 && interface.at(1).isUpper()) {
+ if (interface.startsWith("QDBus"_L1)) {
+ interface.prepend("org.qtproject.QtDBus."_L1);
+ } else if (interface.startsWith(u'Q') &&
+ interface.size() >= 2 && interface.at(1).isUpper()) {
// assume it's Qt
- interface.prepend(QLatin1String("local.org.qtproject.Qt."));
+ interface.prepend("local.org.qtproject.Qt."_L1);
} else {
- interface.prepend(QLatin1String("local."));
+ interface.prepend("local."_L1);
}
return interface;
@@ -358,16 +336,16 @@ static std::deque<CustomType> s_customTypes;
static void parseCmdLine(QStringList &arguments)
{
flags = 0;
- for (int i = 0; i < arguments.count(); ++i) {
+ for (qsizetype i = 0; i < arguments.size(); ++i) {
const QString arg = arguments.at(i);
- if (arg == QLatin1String("--help"))
+ if (arg == "--help"_L1)
showHelp();
- if (!arg.startsWith(QLatin1Char('-')))
+ if (!arg.startsWith(u'-'))
continue;
- char c = arg.count() == 2 ? arg.at(1).toLatin1() : char(0);
+ char c = arg.size() == 2 ? arg.at(1).toLatin1() : char(0);
switch (c) {
case 'P':
flags |= QDBusConnection::ExportNonScriptableProperties;
@@ -398,13 +376,13 @@ static void parseCmdLine(QStringList &arguments)
break;
case 't':
- if (arguments.count() < i + 2) {
+ if (arguments.size() < i + 2) {
printf("-t expects a type=dbustype argument\n");
exit(1);
} else {
const QByteArray arg = arguments.takeAt(i + 1).toUtf8();
// lastIndexOf because the C++ type could contain '=' while the DBus type can't
- const int separator = arg.lastIndexOf('=');
+ const qsizetype separator = arg.lastIndexOf('=');
if (separator == -1) {
printf("-t expects a type=dbustype argument, but no '=' was found\n");
exit(1);
@@ -419,7 +397,7 @@ static void parseCmdLine(QStringList &arguments)
break;
case 'o':
- if (arguments.count() < i + 2 || arguments.at(i + 1).startsWith(QLatin1Char('-'))) {
+ if (arguments.size() < i + 2 || arguments.at(i + 1).startsWith(u'-')) {
printf("-o expects a filename\n");
exit(1);
}
@@ -454,18 +432,30 @@ int main(int argc, char **argv)
args.append(QString::fromLocal8Bit(argv[n]));
parseCmdLine(args);
- QList<ClassDef> classes;
+ QDBusMetaTypeId::init();
- for (int i = 0; i < args.count(); ++i) {
- const QString arg = args.at(i);
+ QList<ClassDef> classes;
- if (arg.startsWith(QLatin1Char('-')))
+ if (args.isEmpty())
+ args << u"-"_s;
+ for (const auto &arg: std::as_const(args)) {
+ if (arg.startsWith(u'-') && arg.size() > 1)
continue;
- QFile f(arg);
- if (!f.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ QFile f;
+ bool fileIsOpen;
+ QString fileName;
+ if (arg == u'-') {
+ fileName = "stdin"_L1;
+ fileIsOpen = f.open(stdin, QIODevice::ReadOnly | QIODevice::Text);
+ } else {
+ fileName = arg;
+ f.setFileName(arg);
+ fileIsOpen = f.open(QIODevice::ReadOnly | QIODevice::Text);
+ }
+ if (!fileIsOpen) {
fprintf(stderr, PROGRAMNAME ": could not open '%s': %s\n",
- qPrintable(arg), qPrintable(f.errorString()));
+ qPrintable(fileName), qPrintable(f.errorString()));
return 1;
}
@@ -491,11 +481,15 @@ int main(int argc, char **argv)
QFile output;
if (outputFile.isEmpty()) {
- output.open(stdout, QIODevice::WriteOnly);
+ if (!output.open(stdout, QIODevice::WriteOnly)) {
+ fprintf(stderr, PROGRAMNAME ": could not open standard output: %s\n",
+ qPrintable(output.errorString()));
+ return 1;
+ }
} else {
output.setFileName(outputFile);
if (!output.open(QIODevice::WriteOnly)) {
- fprintf(stderr, PROGRAMNAME ": could not open output file '%s': %s",
+ fprintf(stderr, PROGRAMNAME ": could not open output file '%s': %s\n",
qPrintable(outputFile), qPrintable(output.errorString()));
return 1;
}
@@ -503,7 +497,7 @@ int main(int argc, char **argv)
output.write(docTypeHeader);
output.write("<node>\n");
- for (const ClassDef &cdef : qAsConst(classes)) {
+ for (const ClassDef &cdef : std::as_const(classes)) {
QString xml = qDBusGenerateClassDefXml(&cdef);
output.write(std::move(xml).toLocal8Bit());
}
diff --git a/src/tools/qdbusxml2cpp/CMakeLists.txt b/src/tools/qdbusxml2cpp/CMakeLists.txt
index 45795952b4..0da22ebfc6 100644
--- a/src/tools/qdbusxml2cpp/CMakeLists.txt
+++ b/src/tools/qdbusxml2cpp/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from qdbusxml2cpp.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## qdbusxml2cpp Tool:
@@ -6,33 +7,16 @@
qt_get_tool_target_name(target_name qdbusxml2cpp)
qt_internal_add_tool(${target_name}
+ TRY_RUN
TARGET_DESCRIPTION "Qt D-Bus XML to C++ Compiler"
- TOOLS_TARGET DBus # special case
+ TOOLS_TARGET DBus
SOURCES
qdbusxml2cpp.cpp
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_FOREACH
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::CorePrivate
Qt::DBusPrivate
- # COMPILE_OPTIONS # special case
- # "$$QT_HOST_CFLAGS_DBUS"
- # QMAKE_TARGET_DESCRIPTION = "Qt D-Bus XML to C++ Compiler"
- # _LOADED = "qt_tool"
- # _OPTION = "host_build"
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:qdbusxml2cpp.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt D-Bus XML to C++ Compiler"
-# _OPTION = "host_build"
-
-## Scopes:
-#####################################################################
-
-# special case begin
-# qt_internal_extend_target(qdbusxml2cpp CONDITION NOT force_bootstrap [...])
-# qt_internal_extend_target(qdbusxml2cpp CONDITION NOT QT_FEATURE_commandlineparser AND NOT force_bootstrap [...])
-# qt_internal_extend_target(qdbusxml2cpp CONDITION force_bootstrap [...])
-# special case end
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
index 825ef1dec1..579604286c 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <qbytearray.h>
#include <qcommandlineparser.h>
@@ -46,21 +21,75 @@
#define PROGRAMNAME "qdbusxml2cpp"
#define PROGRAMVERSION "0.8"
-#define PROGRAMCOPYRIGHT "Copyright (C) 2022 The Qt Company Ltd."
+#define PROGRAMCOPYRIGHT QT_COPYRIGHT
#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
-static QString globalClassName;
-static QString parentClassName;
-static QString proxyFile;
-static QString adaptorFile;
-static QString inputFile;
-static bool skipNamespaces;
-static bool verbose;
-static bool includeMocs;
-static QString commandLine;
-static QStringList includes;
-static QStringList wantedInterfaces;
+using namespace Qt::StringLiterals;
+
+class QDBusXmlToCpp final
+{
+public:
+ int run(const QCoreApplication &app);
+
+private:
+ class DiagnosticsReporter final : public QDBusIntrospection::DiagnosticsReporter
+ {
+ public:
+ void setFileName(const QString &fileName) { m_fileName = fileName; }
+ bool hadErrors() const { return m_hadErrors; }
+
+ void warning(const QDBusIntrospection::SourceLocation &location, const char *msg,
+ ...) override;
+ void error(const QDBusIntrospection::SourceLocation &location, const char *msg,
+ ...) override;
+ void note(const QDBusIntrospection::SourceLocation &location, const char *msg, ...)
+ Q_ATTRIBUTE_FORMAT_PRINTF(3, 4);
+
+ private:
+ QString m_fileName;
+ bool m_hadErrors = false;
+
+ void report(const QDBusIntrospection::SourceLocation &location, const char *msg, va_list ap,
+ const char *severity);
+ };
+
+ enum ClassType { Proxy, Adaptor };
+
+ void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces);
+ void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces);
+
+ QDBusIntrospection::Interfaces readInput();
+ void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces);
+ QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost);
+ QString classNameForInterface(const QString &interface, ClassType classType);
+ QByteArray qtTypeName(const QDBusIntrospection::SourceLocation &location,
+ const QString &signature,
+ const QDBusIntrospection::Annotations &annotations,
+ qsizetype paramId = -1, const char *direction = "Out");
+ void
+ writeArgList(QTextStream &ts, const QStringList &argNames,
+ const QDBusIntrospection::Annotations &annotations,
+ const QDBusIntrospection::Arguments &inputArgs,
+ const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments());
+ void writeSignalArgList(QTextStream &ts, const QStringList &argNames,
+ const QDBusIntrospection::Annotations &annotations,
+ const QDBusIntrospection::Arguments &outputArgs);
+ QString propertyGetter(const QDBusIntrospection::Property &property);
+ QString propertySetter(const QDBusIntrospection::Property &property);
+
+ QString globalClassName;
+ QString parentClassName;
+ QString inputFile;
+ bool skipNamespaces = false;
+ bool includeMocs = false;
+ QString commandLine;
+ QStringList includes;
+ QStringList globalIncludes;
+ QStringList wantedInterfaces;
+
+ DiagnosticsReporter reporter;
+};
static const char includeList[] =
"#include <QtCore/QByteArray>\n"
@@ -73,30 +102,71 @@ static const char includeList[] =
static const char forwardDeclarations[] =
"#include <QtCore/qcontainerfwd.h>\n";
-static QDBusIntrospection::Interfaces readInput()
+void QDBusXmlToCpp::DiagnosticsReporter::warning(const QDBusIntrospection::SourceLocation &location,
+ const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ report(location, msg, ap, "warning");
+ va_end(ap);
+}
+
+void QDBusXmlToCpp::DiagnosticsReporter::error(const QDBusIntrospection::SourceLocation &location,
+ const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ report(location, msg, ap, "error");
+ va_end(ap);
+ m_hadErrors = true;
+}
+
+void QDBusXmlToCpp::DiagnosticsReporter::note(const QDBusIntrospection::SourceLocation &location,
+ const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ report(location, msg, ap, "note");
+ va_end(ap);
+ m_hadErrors = true;
+}
+
+void QDBusXmlToCpp::DiagnosticsReporter::report(const QDBusIntrospection::SourceLocation &location,
+ const char *msg, va_list ap, const char *severity)
+{
+ fprintf(stderr, "%s:%lld:%lld: %s: ", qPrintable(m_fileName),
+ (long long int)location.lineNumber, (long long int)location.columnNumber + 1, severity);
+ vfprintf(stderr, msg, ap);
+}
+
+QDBusIntrospection::Interfaces QDBusXmlToCpp::readInput()
{
QFile input(inputFile);
- if (inputFile.isEmpty() || inputFile == QLatin1String("-")) {
- input.open(stdin, QIODevice::ReadOnly);
+ if (inputFile.isEmpty() || inputFile == "-"_L1) {
+ reporter.setFileName("<standard input>"_L1);
+ if (!input.open(stdin, QIODevice::ReadOnly)) {
+ fprintf(stderr, PROGRAMNAME ": could not open standard input: %s\n",
+ qPrintable(input.errorString()));
+ exit(1);
+ }
} else {
- input.open(QIODevice::ReadOnly);
+ reporter.setFileName(inputFile);
+ if (!input.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, PROGRAMNAME ": could not open input file '%s': %s\n",
+ qPrintable(inputFile), qPrintable(input.errorString()));
+ exit(1);
+ }
}
QByteArray data = input.readAll();
+ auto interfaces = QDBusIntrospection::parseInterfaces(QString::fromUtf8(data), &reporter);
+ if (reporter.hadErrors())
+ exit(1);
- // check if the input is already XML
- data = data.trimmed();
- if (data.startsWith("<!DOCTYPE ") || data.startsWith("<?xml") ||
- data.startsWith("<node") || data.startsWith("<interface"))
- // already XML
- return QDBusIntrospection::parseInterfaces(QString::fromUtf8(data));
-
- fprintf(stderr, "%s: Cannot process input: '%s'. Stop.\n",
- PROGRAMNAME, qPrintable(inputFile));
- exit(1);
+ return interfaces;
}
-static void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
+void QDBusXmlToCpp::cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
{
if (!wantedInterfaces.isEmpty()) {
QDBusIntrospection::Interfaces::Iterator it = interfaces.begin();
@@ -108,18 +178,33 @@ static void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
}
}
+static bool isSupportedSuffix(QStringView suffix)
+{
+ const QLatin1StringView candidates[] = {
+ "h"_L1,
+ "cpp"_L1,
+ "cc"_L1
+ };
+
+ for (auto candidate : candidates)
+ if (suffix == candidate)
+ return true;
+
+ return false;
+}
+
// produce a header name from the file name
static QString header(const QString &name)
{
- QStringList parts = name.split(QLatin1Char(':'));
- QString retval = parts.first();
+ QStringList parts = name.split(u':');
+ QString retval = parts.front();
- if (retval.isEmpty() || retval == QLatin1String("-"))
+ if (retval.isEmpty() || retval == "-"_L1)
return retval;
- if (!retval.endsWith(QLatin1String(".h")) && !retval.endsWith(QLatin1String(".cpp")) &&
- !retval.endsWith(QLatin1String(".cc")))
- retval.append(QLatin1String(".h"));
+ QFileInfo header{retval};
+ if (!isSupportedSuffix(header.suffix()))
+ retval.append(".h"_L1);
return retval;
}
@@ -127,15 +212,15 @@ static QString header(const QString &name)
// produce a cpp name from the file name
static QString cpp(const QString &name)
{
- QStringList parts = name.split(QLatin1Char(':'));
- QString retval = parts.last();
+ QStringList parts = name.split(u':');
+ QString retval = parts.back();
- if (retval.isEmpty() || retval == QLatin1String("-"))
+ if (retval.isEmpty() || retval == "-"_L1)
return retval;
- if (!retval.endsWith(QLatin1String(".h")) && !retval.endsWith(QLatin1String(".cpp")) &&
- !retval.endsWith(QLatin1String(".cc")))
- retval.append(QLatin1String(".cpp"));
+ QFileInfo source{retval};
+ if (!isSupportedSuffix(source.suffix()))
+ retval.append(".cpp"_L1);
return retval;
}
@@ -143,44 +228,78 @@ static QString cpp(const QString &name)
// produce a moc name from the file name
static QString moc(const QString &name)
{
- QString retval = header(name);
- if (retval.isEmpty())
- return retval;
+ QString retval;
+ const QStringList fileNames = name.split(u':');
+
+ if (fileNames.size() == 1) {
+ QFileInfo fi{fileNames.front()};
+ if (isSupportedSuffix(fi.suffix())) {
+ // Generates a file that contains the header and the implementation: include "filename.moc"
+ retval += fi.completeBaseName();
+ retval += ".moc"_L1;
+ } else {
+ // Separate source and header files are generated: include "moc_filename.cpp"
+ retval += "moc_"_L1;
+ retval += fi.fileName();
+ retval += ".cpp"_L1;
+ }
+ } else {
+ QString headerName = fileNames.front();
+ QString sourceName = fileNames.back();
+
+ if (sourceName.isEmpty() || sourceName == "-"_L1) {
+ // If only a header is generated, don't include anything
+ } else if (headerName.isEmpty() || headerName == "-"_L1) {
+ // If only source file is generated: include "moc_sourcename.cpp"
+ QFileInfo source{sourceName};
+
+ retval += "moc_"_L1;
+ retval += source.completeBaseName();
+ retval += ".cpp"_L1;
+
+ fprintf(stderr, "warning: no header name is provided, assuming it to be \"%s\"\n",
+ qPrintable(source.completeBaseName() + ".h"_L1));
+ } else {
+ // Both source and header generated: include "moc_headername.cpp"
+ QFileInfo header{headerName};
+
+ retval += "moc_"_L1;
+ retval += header.completeBaseName();
+ retval += ".cpp"_L1;
+ }
+ }
- retval.truncate(retval.length() - 1); // drop the h in .h
- retval += QLatin1String("moc");
return retval;
}
-static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost)
+QTextStream &QDBusXmlToCpp::writeHeader(QTextStream &ts, bool changesWillBeLost)
{
- ts << "/*" << Qt::endl
- << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << Qt::endl
- << " * Command line was: " << commandLine << Qt::endl
- << " *" << Qt::endl
- << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << Qt::endl
- << " *" << Qt::endl
- << " * This is an auto-generated file." << Qt::endl;
+ ts << "/*\n"
+ " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION "\n"
+ " * Command line was: " << commandLine << "\n"
+ " *\n"
+ " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT "\n"
+ " *\n"
+ " * This is an auto-generated file.\n";
if (changesWillBeLost)
- ts << " * Do not edit! All changes made to it will be lost." << Qt::endl;
+ ts << " * Do not edit! All changes made to it will be lost.\n";
else
- ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << Qt::endl
- << " * before re-generating it." << Qt::endl;
+ ts << " * This file may have been hand-edited. Look for HAND-EDIT comments\n"
+ " * before re-generating it.\n";
- ts << " */" << Qt::endl
- << Qt::endl;
+ ts << " */\n\n";
return ts;
}
-enum ClassType { Proxy, Adaptor };
-static QString classNameForInterface(const QString &interface, ClassType classType)
+QString QDBusXmlToCpp::classNameForInterface(const QString &interface,
+ QDBusXmlToCpp::ClassType classType)
{
if (!globalClassName.isEmpty())
return globalClassName;
- const auto parts = QStringView{interface}.split(QLatin1Char('.'));
+ const auto parts = QStringView{interface}.split(u'.');
QString retval;
if (classType == Proxy) {
@@ -193,50 +312,46 @@ static QString classNameForInterface(const QString &interface, ClassType classTy
}
if (classType == Proxy)
- retval += QLatin1String("Interface");
+ retval += "Interface"_L1;
else
- retval += QLatin1String("Adaptor");
+ retval += "Adaptor"_L1;
return retval;
}
-// ### Qt6 Remove the two isSignal ifs
-// They are only here because before signal arguments where previously searched as "In" so to maintain compatibility
-// we first search for "Out" and if not found we search for "In"
-static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection::Annotations &annotations, int paramId = -1, const char *direction = "Out", bool isSignal = false)
+QByteArray QDBusXmlToCpp::qtTypeName(const QDBusIntrospection::SourceLocation &location,
+ const QString &signature,
+ const QDBusIntrospection::Annotations &annotations,
+ qsizetype paramId, const char *direction)
{
int type = QDBusMetaType::signatureToMetaType(signature.toLatin1()).id();
if (type == QMetaType::UnknownType) {
- QString annotationName = QString::fromLatin1("org.qtproject.QtDBus.QtTypeName");
+ QString annotationName = u"org.qtproject.QtDBus.QtTypeName"_s;
if (paramId >= 0)
- annotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId);
- QString qttype = annotations.value(annotationName);
+ annotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId);
+ auto annotation = annotations.value(annotationName);
+ QString qttype = annotation.value;
if (!qttype.isEmpty())
return std::move(qttype).toLatin1();
- QString oldAnnotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName");
+ QString oldAnnotationName = u"com.trolltech.QtDBus.QtTypeName"_s;
if (paramId >= 0)
- oldAnnotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId);
- qttype = annotations.value(oldAnnotationName);
+ oldAnnotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId);
+ annotation = annotations.value(oldAnnotationName);
+ qttype = annotation.value;
if (qttype.isEmpty()) {
- if (!isSignal || qstrcmp(direction, "Out") == 0) {
- fprintf(stderr, "%s: Got unknown type `%s' processing '%s'\n",
- PROGRAMNAME, qPrintable(signature), qPrintable(inputFile));
- fprintf(stderr, "You should add <annotation name=\"%s\" value=\"<type>\"/> to the XML description\n",
- qPrintable(annotationName));
- }
-
- if (isSignal)
- return qtTypeName(signature, annotations, paramId, "In", isSignal);
+ reporter.error(location, "unknown type `%s'\n", qPrintable(signature));
+ reporter.note(location, "you should add <annotation name=\"%s\" value=\"<type>\"/>\n",
+ qPrintable(annotationName));
exit(1);
}
- fprintf(stderr, "%s: Warning: deprecated annotation '%s' found while processing '%s'; "
- "suggest updating to '%s'\n",
- PROGRAMNAME, qPrintable(oldAnnotationName), qPrintable(inputFile),
- qPrintable(annotationName));
+ reporter.warning(annotation.location, "deprecated annotation '%s' found\n",
+ qPrintable(oldAnnotationName));
+ reporter.note(annotation.location, "suggest updating to '%s'\n",
+ qPrintable(annotationName));
return std::move(qttype).toLatin1();
}
@@ -245,23 +360,23 @@ static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection:
static QString nonConstRefArg(const QByteArray &arg)
{
- return QLatin1String(arg + " &");
+ return QLatin1StringView(arg) + " &"_L1;
}
static QString templateArg(const QByteArray &arg)
{
if (!arg.endsWith('>'))
- return QLatin1String(arg);
+ return QLatin1StringView(arg);
- return QLatin1String(arg + ' ');
+ return QLatin1StringView(arg) + " "_L1;
}
static QString constRefArg(const QByteArray &arg)
{
if (!arg.startsWith('Q'))
- return QLatin1String(arg + ' ');
+ return QLatin1StringView(arg) + " "_L1;
else
- return QString( QLatin1String("const %1 &") ).arg( QLatin1String(arg) );
+ return "const %1 &"_L1.arg(QLatin1StringView(arg));
}
static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs,
@@ -269,45 +384,45 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs,
QDBusIntrospection::Arguments())
{
QStringList retval;
- const int numInputArgs = inputArgs.count();
- const int numOutputArgs = outputArgs.count();
+ const qsizetype numInputArgs = inputArgs.size();
+ const qsizetype numOutputArgs = outputArgs.size();
retval.reserve(numInputArgs + numOutputArgs);
- for (int i = 0; i < numInputArgs; ++i) {
+ for (qsizetype i = 0; i < numInputArgs; ++i) {
const QDBusIntrospection::Argument &arg = inputArgs.at(i);
QString name = arg.name;
if (name.isEmpty())
- name = QString( QLatin1String("in%1") ).arg(i);
+ name = u"in%1"_s.arg(i);
else
- name.replace(QLatin1Char('-'), QLatin1Char('_'));
+ name.replace(u'-', u'_');
while (retval.contains(name))
- name += QLatin1String("_");
+ name += "_"_L1;
retval << name;
}
- for (int i = 0; i < numOutputArgs; ++i) {
+ for (qsizetype i = 0; i < numOutputArgs; ++i) {
const QDBusIntrospection::Argument &arg = outputArgs.at(i);
QString name = arg.name;
if (name.isEmpty())
- name = QString( QLatin1String("out%1") ).arg(i);
+ name = u"out%1"_s.arg(i);
else
- name.replace(QLatin1Char('-'), QLatin1Char('_'));
+ name.replace(u'-', u'_');
while (retval.contains(name))
- name += QLatin1String("_");
+ name += "_"_L1;
retval << name;
}
return retval;
}
-static void writeArgList(QTextStream &ts, const QStringList &argNames,
- const QDBusIntrospection::Annotations &annotations,
- const QDBusIntrospection::Arguments &inputArgs,
- const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments())
+void QDBusXmlToCpp::writeArgList(QTextStream &ts, const QStringList &argNames,
+ const QDBusIntrospection::Annotations &annotations,
+ const QDBusIntrospection::Arguments &inputArgs,
+ const QDBusIntrospection::Arguments &outputArgs)
{
// input args:
bool first = true;
- int argPos = 0;
- for (int i = 0; i < inputArgs.count(); ++i) {
+ qsizetype argPos = 0;
+ for (qsizetype i = 0; i < inputArgs.size(); ++i) {
const QDBusIntrospection::Argument &arg = inputArgs.at(i);
- QString type = constRefArg(qtTypeName(arg.type, annotations, i, "In"));
+ QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "In"));
if (!first)
ts << ", ";
@@ -319,26 +434,26 @@ static void writeArgList(QTextStream &ts, const QStringList &argNames,
// output args
// yes, starting from 1
- for (int i = 1; i < outputArgs.count(); ++i) {
+ for (qsizetype i = 1; i < outputArgs.size(); ++i) {
const QDBusIntrospection::Argument &arg = outputArgs.at(i);
if (!first)
ts << ", ";
- ts << nonConstRefArg(qtTypeName(arg.type, annotations, i, "Out"))
+ ts << nonConstRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out"))
<< argNames.at(argPos++);
first = false;
}
}
-static void writeSignalArgList(QTextStream &ts, const QStringList &argNames,
- const QDBusIntrospection::Annotations &annotations,
- const QDBusIntrospection::Arguments &outputArgs)
+void QDBusXmlToCpp::writeSignalArgList(QTextStream &ts, const QStringList &argNames,
+ const QDBusIntrospection::Annotations &annotations,
+ const QDBusIntrospection::Arguments &outputArgs)
{
bool first = true;
- int argPos = 0;
- for (int i = 0; i < outputArgs.count(); ++i) {
+ qsizetype argPos = 0;
+ for (qsizetype i = 0; i < outputArgs.size(); ++i) {
const QDBusIntrospection::Argument &arg = outputArgs.at(i);
- QString type = constRefArg(qtTypeName(arg.type, annotations, i, "Out", true /* isSignal */));
+ QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out"));
if (!first)
ts << ", ";
@@ -347,49 +462,49 @@ static void writeSignalArgList(QTextStream &ts, const QStringList &argNames,
}
}
-static QString propertyGetter(const QDBusIntrospection::Property &property)
+QString QDBusXmlToCpp::propertyGetter(const QDBusIntrospection::Property &property)
{
- QString getter = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertyGetter"));
- if (!getter.isEmpty())
- return getter;
-
- getter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertyGetter"));
- if (!getter.isEmpty()) {
- fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found"
- " while processing '%s';"
- " suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n",
- PROGRAMNAME, qPrintable(inputFile));
- return getter;
+ auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1);
+ if (!annotation.value.isEmpty())
+ return annotation.value;
+
+ annotation = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1);
+ if (!annotation.value.isEmpty()) {
+ reporter.warning(annotation.location,
+ "deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found\n");
+ reporter.note(annotation.location,
+ "suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n");
+ return annotation.value;
}
- getter = property.name;
+ QString getter = property.name;
getter[0] = getter[0].toLower();
return getter;
}
-static QString propertySetter(const QDBusIntrospection::Property &property)
+QString QDBusXmlToCpp::propertySetter(const QDBusIntrospection::Property &property)
{
- QString setter = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertySetter"));
- if (!setter.isEmpty())
- return setter;
-
- setter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertySetter"));
- if (!setter.isEmpty()) {
- fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found"
- " while processing '%s';"
- " suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n",
- PROGRAMNAME, qPrintable(inputFile));
- return setter;
+ auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1);
+ if (!annotation.value.isEmpty())
+ return annotation.value;
+
+ annotation = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1);
+ if (!annotation.value.isEmpty()) {
+ reporter.warning(annotation.location,
+ "deprecated annotation 'com.trolltech.QtDBus.propertySetter' found\n");
+ reporter.note(annotation.location,
+ "suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n");
+ return annotation.value;
}
- setter = QLatin1String("set") + property.name;
+ QString setter = "set"_L1 + property.name;
setter[3] = setter[3].toUpper();
return setter;
}
static QString methodName(const QDBusIntrospection::Method &method)
{
- QString name = method.annotations.value(QStringLiteral("org.qtproject.QtDBus.MethodName"));
+ QString name = method.annotations.value(u"org.qtproject.QtDBus.MethodName"_s).value;
if (!name.isEmpty())
return name;
@@ -399,17 +514,17 @@ static QString methodName(const QDBusIntrospection::Method &method)
static QString stringify(const QString &data)
{
QString retval;
- int i;
- for (i = 0; i < data.length(); ++i) {
- retval += QLatin1Char('\"');
- for ( ; i < data.length() && data[i] != QLatin1Char('\n') && data[i] != QLatin1Char('\r'); ++i)
- if (data[i] == QLatin1Char('\"'))
- retval += QLatin1String("\\\"");
+ qsizetype i;
+ for (i = 0; i < data.size(); ++i) {
+ retval += u'\"';
+ for ( ; i < data.size() && data[i] != u'\n' && data[i] != u'\r'; ++i)
+ if (data[i] == u'\"')
+ retval += "\\\""_L1;
else
retval += data[i];
- if (i+1 < data.length() && data[i] == QLatin1Char('\r') && data[i+1] == QLatin1Char('\n'))
+ if (i+1 < data.size() && data[i] == u'\r' && data[i+1] == u'\n')
i++;
- retval += QLatin1String("\\n\"\n");
+ retval += "\\n\"\n"_L1;
}
return retval;
}
@@ -420,7 +535,7 @@ static bool openFile(const QString &fileName, QFile &file)
return false;
bool isOk = false;
- if (fileName == QLatin1String("-")) {
+ if (fileName == "-"_L1) {
isOk = file.open(stdout, QIODevice::WriteOnly | QIODevice::Text);
} else {
file.setFileName(fileName);
@@ -433,7 +548,8 @@ static bool openFile(const QString &fileName, QFile &file)
return isOk;
}
-static void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces)
+void QDBusXmlToCpp::writeProxy(const QString &filename,
+ const QDBusIntrospection::Interfaces &interfaces)
{
// open the file
QString headerName = header(filename);
@@ -451,85 +567,83 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
// include guards:
QString includeGuard;
- if (!headerName.isEmpty() && headerName != QLatin1String("-")) {
- includeGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_'));
- int pos = includeGuard.lastIndexOf(QLatin1Char('/'));
+ if (!headerName.isEmpty() && headerName != "-"_L1) {
+ includeGuard = headerName.toUpper().replace(u'.', u'_');
+ qsizetype pos = includeGuard.lastIndexOf(u'/');
if (pos != -1)
includeGuard = includeGuard.mid(pos + 1);
} else {
- includeGuard = QLatin1String("QDBUSXML2CPP_PROXY");
+ includeGuard = u"QDBUSXML2CPP_PROXY"_s;
}
- includeGuard = QString(QLatin1String("%1"))
- .arg(includeGuard);
- hs << "#ifndef " << includeGuard << Qt::endl
- << "#define " << includeGuard << Qt::endl
- << Qt::endl;
+
+ hs << "#ifndef " << includeGuard << "\n"
+ "#define " << includeGuard << "\n\n";
// include our stuff:
- hs << "#include <QtCore/QObject>" << Qt::endl
+ hs << "#include <QtCore/QObject>\n"
<< includeList;
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
- hs << "#include <QtDBus/QtDBus>" << Qt::endl;
+ hs << "#include <QtDBus/QtDBus>\n";
#else
- hs << "#include <QtDBus/QDBusAbstractInterface>" << Qt::endl;
- hs << "#include <QtDBus/QDBusPendingReply>" << Qt::endl;
+ hs << "#include <QtDBus/QDBusAbstractInterface>\n"
+ "#include <QtDBus/QDBusPendingReply>\n";
#endif
- for (const QString &include : qAsConst(includes)) {
- hs << "#include \"" << include << "\"" << Qt::endl;
+ for (const QString &include : std::as_const(includes)) {
+ hs << "#include \"" << include << "\"\n";
+ if (headerName.isEmpty())
+ cs << "#include \"" << include << "\"\n";
+ }
+
+ for (const QString &include : std::as_const(globalIncludes)) {
+ hs << "#include <" << include << ">\n";
if (headerName.isEmpty())
- cs << "#include \"" << include << "\"" << Qt::endl;
+ cs << "#include <" << include << ">\n";
}
- hs << Qt::endl;
+ hs << "\n";
if (cppName != headerName) {
- if (!headerName.isEmpty() && headerName != QLatin1String("-"))
- cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl;
+ if (!headerName.isEmpty() && headerName != "-"_L1)
+ cs << "#include \"" << headerName << "\"\n\n";
}
for (const QDBusIntrospection::Interface *interface : interfaces) {
QString className = classNameForInterface(interface->name, Proxy);
// comment:
- hs << "/*" << Qt::endl
- << " * Proxy class for interface " << interface->name << Qt::endl
- << " */" << Qt::endl;
- cs << "/*" << Qt::endl
- << " * Implementation of interface class " << className << Qt::endl
- << " */" << Qt::endl
- << Qt::endl;
+ hs << "/*\n"
+ " * Proxy class for interface " << interface->name << "\n"
+ " */\n";
+ cs << "/*\n"
+ " * Implementation of interface class " << className << "\n"
+ " */\n\n";
// class header:
- hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl
- << "{" << Qt::endl
- << " Q_OBJECT" << Qt::endl;
+ hs << "class " << className << ": public QDBusAbstractInterface\n"
+ "{\n"
+ " Q_OBJECT\n";
// the interface name
- hs << "public:" << Qt::endl
- << " static inline const char *staticInterfaceName()" << Qt::endl
- << " { return \"" << interface->name << "\"; }" << Qt::endl
- << Qt::endl;
+ hs << "public:\n"
+ " static inline const char *staticInterfaceName()\n"
+ " { return \"" << interface->name << "\"; }\n\n";
// constructors/destructors:
- hs << "public:" << Qt::endl
- << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl
- << Qt::endl
- << " ~" << className << "();" << Qt::endl
- << Qt::endl;
- cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl
- << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl
- << "{" << Qt::endl
- << "}" << Qt::endl
- << Qt::endl
- << className << "::~" << className << "()" << Qt::endl
- << "{" << Qt::endl
- << "}" << Qt::endl
- << Qt::endl;
+ hs << "public:\n"
+ " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);\n\n"
+ " ~" << className << "();\n\n";
+ cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)\n"
+ " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)\n"
+ "{\n"
+ "}\n\n"
+ << className << "::~" << className << "()\n"
+ "{\n"
+ "}\n\n";
// properties:
for (const QDBusIntrospection::Property &property : interface->properties) {
- QByteArray type = qtTypeName(property.type, property.annotations);
+ QByteArray type = qtTypeName(property.location, property.type, property.annotations);
QString getter = propertyGetter(property);
QString setter = propertySetter(property);
@@ -545,48 +659,53 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
// it's writeable
hs << " WRITE " << setter;
- hs << ")" << Qt::endl;
+ hs << ")\n";
// getter:
if (property.access != QDBusIntrospection::Property::Write) {
- hs << " inline " << type << " " << getter << "() const" << Qt::endl
- << " { return qvariant_cast< " << type << " >(property(\""
- << property.name << "\")); }" << Qt::endl;
+ hs << " inline " << type << " " << getter << "() const\n"
+ " { return qvariant_cast< " << type << " >(property(\""
+ << property.name << "\")); }\n";
}
// setter:
if (property.access != QDBusIntrospection::Property::Read) {
- hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl
- << " { setProperty(\"" << property.name
- << "\", QVariant::fromValue(value)); }" << Qt::endl;
+ hs << " inline void " << setter << "(" << constRefArg(type) << "value)\n"
+ " { setProperty(\"" << property.name
+ << "\", QVariant::fromValue(value)); }\n";
}
- hs << Qt::endl;
+ hs << "\n";
}
// methods:
- hs << "public Q_SLOTS: // METHODS" << Qt::endl;
+ hs << "public Q_SLOTS: // METHODS\n";
for (const QDBusIntrospection::Method &method : interface->methods) {
- bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true");
- bool isNoReply =
- method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true");
+ bool isDeprecated = method.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value
+ == "true"_L1;
+ bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1;
if (isNoReply && !method.outputArgs.isEmpty()) {
- fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n",
- PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name),
- qPrintable(interface->name));
+ reporter.warning(method.location,
+ "method %s in interface %s is marked 'no-reply' but has output "
+ "arguments.\n",
+ qPrintable(method.name), qPrintable(interface->name));
continue;
}
- hs << " inline "
- << (isDeprecated ? "Q_DECL_DEPRECATED " : "");
+ if (isDeprecated)
+ hs << " Q_DECL_DEPRECATED ";
+ else
+ hs << " ";
if (isNoReply) {
- hs << "Q_NOREPLY void ";
+ hs << "Q_NOREPLY inline void ";
} else {
- hs << "QDBusPendingReply<";
- for (int i = 0; i < method.outputArgs.count(); ++i)
+ hs << "inline QDBusPendingReply<";
+ for (qsizetype i = 0; i < method.outputArgs.size(); ++i)
hs << (i > 0 ? ", " : "")
- << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out"));
+ << templateArg(qtTypeName(method.outputArgs.at(i).location,
+ method.outputArgs.at(i).type, method.annotations,
+ i, "Out"));
hs << "> ";
}
@@ -595,75 +714,77 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
QStringList argNames = makeArgNames(method.inputArgs);
writeArgList(hs, argNames, method.annotations, method.inputArgs);
- hs << ")" << Qt::endl
- << " {" << Qt::endl
- << " QList<QVariant> argumentList;" << Qt::endl;
+ hs << ")\n"
+ " {\n"
+ " QList<QVariant> argumentList;\n";
if (!method.inputArgs.isEmpty()) {
hs << " argumentList";
- for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos)
+ for (qsizetype argPos = 0; argPos < method.inputArgs.size(); ++argPos)
hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')';
- hs << ";" << Qt::endl;
+ hs << ";\n";
}
if (isNoReply)
hs << " callWithArgumentList(QDBus::NoBlock, "
- << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl;
+ "QStringLiteral(\"" << method.name << "\"), argumentList);\n";
else
hs << " return asyncCallWithArgumentList(QStringLiteral(\""
- << method.name << "\"), argumentList);" << Qt::endl;
+ << method.name << "\"), argumentList);\n";
// close the function:
- hs << " }" << Qt::endl;
+ hs << " }\n";
- if (method.outputArgs.count() > 1) {
+ if (method.outputArgs.size() > 1) {
// generate the old-form QDBusReply methods with multiple incoming parameters
- hs << " inline "
- << (isDeprecated ? "Q_DECL_DEPRECATED " : "")
- << "QDBusReply<"
- << templateArg(qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out")) << "> ";
+ hs << (isDeprecated ? " Q_DECL_DEPRECATED " : " ") << "inline QDBusReply<"
+ << templateArg(qtTypeName(method.outputArgs.first().location,
+ method.outputArgs.first().type, method.annotations, 0,
+ "Out"))
+ << "> ";
hs << method.name << "(";
QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
- hs << ")" << Qt::endl
- << " {" << Qt::endl
- << " QList<QVariant> argumentList;" << Qt::endl;
+ hs << ")\n"
+ " {\n"
+ " QList<QVariant> argumentList;\n";
- int argPos = 0;
+ qsizetype argPos = 0;
if (!method.inputArgs.isEmpty()) {
hs << " argumentList";
- for (argPos = 0; argPos < method.inputArgs.count(); ++argPos)
+ for (argPos = 0; argPos < method.inputArgs.size(); ++argPos)
hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')';
- hs << ";" << Qt::endl;
+ hs << ";\n";
}
hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, "
- << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl;
+ "QStringLiteral(\"" << method.name << "\"), argumentList);\n";
argPos++;
- hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == "
- << method.outputArgs.count() << ") {" << Qt::endl;
+ hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().size() == "
+ << method.outputArgs.size() << ") {\n";
// yes, starting from 1
- for (int i = 1; i < method.outputArgs.count(); ++i)
+ for (qsizetype i = 1; i < method.outputArgs.size(); ++i)
hs << " " << argNames.at(argPos++) << " = qdbus_cast<"
- << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out"))
- << ">(reply.arguments().at(" << i << "));" << Qt::endl;
- hs << " }" << Qt::endl
- << " return reply;" << Qt::endl
- << " }" << Qt::endl;
+ << templateArg(qtTypeName(method.outputArgs.at(i).location,
+ method.outputArgs.at(i).type, method.annotations,
+ i, "Out"))
+ << ">(reply.arguments().at(" << i << "));\n";
+ hs << " }\n"
+ " return reply;\n"
+ " }\n";
}
- hs << Qt::endl;
+ hs << "\n";
}
- hs << "Q_SIGNALS: // SIGNALS" << Qt::endl;
+ hs << "Q_SIGNALS: // SIGNALS\n";
for (const QDBusIntrospection::Signal &signal : interface->signals_) {
hs << " ";
- if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
- QLatin1String("true"))
+ if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value == "true"_L1)
hs << "Q_DECL_DEPRECATED ";
hs << "void " << signal.name << "(";
@@ -671,12 +792,11 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
QStringList argNames = makeArgNames(signal.outputArgs);
writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs);
- hs << ");" << Qt::endl; // finished for header
+ hs << ");\n"; // finished for header
}
// close the class:
- hs << "};" << Qt::endl
- << Qt::endl;
+ hs << "};\n\n";
}
if (!skipNamespaces) {
@@ -687,28 +807,28 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
QStringList current;
QString name;
if (it != interfaces.constEnd()) {
- current = it->constData()->name.split(QLatin1Char('.'));
+ current = it->constData()->name.split(u'.');
name = current.takeLast();
}
- int i = 0;
- while (i < current.count() && i < last.count() && current.at(i) == last.at(i))
+ qsizetype i = 0;
+ while (i < current.size() && i < last.size() && current.at(i) == last.at(i))
++i;
// i parts matched
- // close last.arguments().count() - i namespaces:
- for (int j = i; j < last.count(); ++j)
- hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << Qt::endl;
+ // close last.arguments().size() - i namespaces:
+ for (qsizetype j = i; j < last.size(); ++j)
+ hs << QString((last.size() - j - 1 + i) * 2, u' ') << "}\n";
- // open current.arguments().count() - i namespaces
- for (int j = i; j < current.count(); ++j)
- hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << Qt::endl;
+ // open current.arguments().size() - i namespaces
+ for (qsizetype j = i; j < current.size(); ++j)
+ hs << QString(j * 2, u' ') << "namespace " << current.at(j) << " {\n";
// add this class:
if (!name.isEmpty()) {
- hs << QString(current.count() * 2, QLatin1Char(' '))
+ hs << QString(current.size() * 2, u' ')
<< "using " << name << " = ::" << classNameForInterface(it->constData()->name, Proxy)
- << ";" << Qt::endl;
+ << ";\n";
}
if (it == interfaces.constEnd())
@@ -719,12 +839,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
}
// close the include guard
- hs << "#endif" << Qt::endl;
+ hs << "#endif\n";
QString mocName = moc(filename);
if (includeMocs && !mocName.isEmpty())
- cs << Qt::endl
- << "#include \"" << mocName << "\"" << Qt::endl;
+ cs << "\n"
+ "#include \"" << mocName << "\"\n";
cs.flush();
hs.flush();
@@ -744,7 +864,8 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
}
}
-static void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces)
+void QDBusXmlToCpp::writeAdaptor(const QString &filename,
+ const QDBusIntrospection::Interfaces &interfaces)
{
// open the file
QString headerName = header(filename);
@@ -762,103 +883,102 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
// include guards:
QString includeGuard;
- if (!headerName.isEmpty() && headerName != QLatin1String("-")) {
- includeGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_'));
- int pos = includeGuard.lastIndexOf(QLatin1Char('/'));
+ if (!headerName.isEmpty() && headerName != "-"_L1) {
+ includeGuard = headerName.toUpper().replace(u'.', u'_');
+ qsizetype pos = includeGuard.lastIndexOf(u'/');
if (pos != -1)
includeGuard = includeGuard.mid(pos + 1);
} else {
- includeGuard = QLatin1String("QDBUSXML2CPP_ADAPTOR");
+ includeGuard = u"QDBUSXML2CPP_ADAPTOR"_s;
}
- includeGuard = QString(QLatin1String("%1"))
- .arg(includeGuard);
- hs << "#ifndef " << includeGuard << Qt::endl
- << "#define " << includeGuard << Qt::endl
- << Qt::endl;
+
+ hs << "#ifndef " << includeGuard << "\n"
+ "#define " << includeGuard << "\n\n";
// include our stuff:
- hs << "#include <QtCore/QObject>" << Qt::endl;
+ hs << "#include <QtCore/QObject>\n";
if (cppName == headerName)
- hs << "#include <QtCore/QMetaObject>" << Qt::endl
- << "#include <QtCore/QVariant>" << Qt::endl;
+ hs << "#include <QtCore/QMetaObject>\n"
+ "#include <QtCore/QVariant>\n";
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
- hs << "#include <QtDBus/QtDBus>" << Qt::endl;
+ hs << "#include <QtDBus/QtDBus>\n";
#else
- hs << "#include <QtDBus/QDBusAbstractAdaptor>" << Qt::endl;
- hs << "#include <QtDBus/QDBusObjectPath>" << Qt::endl;
+ hs << "#include <QtDBus/QDBusAbstractAdaptor>\n"
+ "#include <QtDBus/QDBusObjectPath>\n";
#endif
- for (const QString &include : qAsConst(includes)) {
- hs << "#include \"" << include << "\"" << Qt::endl;
+ for (const QString &include : std::as_const(includes)) {
+ hs << "#include \"" << include << "\"\n";
+ if (headerName.isEmpty())
+ cs << "#include \"" << include << "\"\n";
+ }
+
+ for (const QString &include : std::as_const(globalIncludes)) {
+ hs << "#include <" << include << ">\n";
if (headerName.isEmpty())
- cs << "#include \"" << include << "\"" << Qt::endl;
+ cs << "#include <" << include << ">\n";
}
if (cppName != headerName) {
- if (!headerName.isEmpty() && headerName != QLatin1String("-"))
- cs << "#include \"" << headerName << "\"" << Qt::endl;
+ if (!headerName.isEmpty() && headerName != "-"_L1)
+ cs << "#include \"" << headerName << "\"\n";
- cs << "#include <QtCore/QMetaObject>" << Qt::endl
+ cs << "#include <QtCore/QMetaObject>\n"
<< includeList
- << Qt::endl;
+ << "\n";
hs << forwardDeclarations;
} else {
hs << includeList;
}
- hs << Qt::endl;
+ hs << "\n";
QString parent = parentClassName;
if (parentClassName.isEmpty())
- parent = QLatin1String("QObject");
+ parent = u"QObject"_s;
for (const QDBusIntrospection::Interface *interface : interfaces) {
QString className = classNameForInterface(interface->name, Adaptor);
// comment:
- hs << "/*" << Qt::endl
- << " * Adaptor class for interface " << interface->name << Qt::endl
- << " */" << Qt::endl;
- cs << "/*" << Qt::endl
- << " * Implementation of adaptor class " << className << Qt::endl
- << " */" << Qt::endl
- << Qt::endl;
+ hs << "/*\n"
+ " * Adaptor class for interface " << interface->name << "\n"
+ " */\n";
+ cs << "/*\n"
+ " * Implementation of adaptor class " << className << "\n"
+ " */\n\n";
// class header:
- hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl
- << "{" << Qt::endl
- << " Q_OBJECT" << Qt::endl
- << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl
- << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl
+ hs << "class " << className << ": public QDBusAbstractAdaptor\n"
+ "{\n"
+ " Q_OBJECT\n"
+ " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")\n"
+ " Q_CLASSINFO(\"D-Bus Introspection\", \"\"\n"
<< stringify(interface->introspection)
- << " \"\")" << Qt::endl
- << "public:" << Qt::endl
- << " " << className << "(" << parent << " *parent);" << Qt::endl
- << " virtual ~" << className << "();" << Qt::endl
- << Qt::endl;
+ << " \"\")\n"
+ "public:\n"
+ " " << className << "(" << parent << " *parent);\n"
+ " ~" << className << "() override;\n\n";
if (!parentClassName.isEmpty())
- hs << " inline " << parent << " *parent() const" << Qt::endl
- << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl
- << Qt::endl;
+ hs << " inline " << parent << " *parent() const\n"
+ " { return static_cast<" << parent << " *>(QObject::parent()); }\n\n";
// constructor/destructor
- cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl
- << " : QDBusAbstractAdaptor(parent)" << Qt::endl
- << "{" << Qt::endl
- << " // constructor" << Qt::endl
- << " setAutoRelaySignals(true);" << Qt::endl
- << "}" << Qt::endl
- << Qt::endl
- << className << "::~" << className << "()" << Qt::endl
- << "{" << Qt::endl
- << " // destructor" << Qt::endl
- << "}" << Qt::endl
- << Qt::endl;
-
- hs << "public: // PROPERTIES" << Qt::endl;
+ cs << className << "::" << className << "(" << parent << " *parent)\n"
+ " : QDBusAbstractAdaptor(parent)\n"
+ "{\n"
+ " // constructor\n"
+ " setAutoRelaySignals(true);\n"
+ "}\n\n"
+ << className << "::~" << className << "()\n"
+ "{\n"
+ " // destructor\n"
+ "}\n\n";
+
+ hs << "public: // PROPERTIES\n";
for (const QDBusIntrospection::Property &property : interface->properties) {
- QByteArray type = qtTypeName(property.type, property.annotations);
+ QByteArray type = qtTypeName(property.location, property.type, property.annotations);
QString constRefType = constRefArg(type);
QString getter = propertyGetter(property);
QString setter = propertySetter(property);
@@ -868,52 +988,47 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
hs << " READ " << getter;
if (property.access != QDBusIntrospection::Property::Read)
hs << " WRITE " << setter;
- hs << ")" << Qt::endl;
+ hs << ")\n";
// getter:
if (property.access != QDBusIntrospection::Property::Write) {
- hs << " " << type << " " << getter << "() const;" << Qt::endl;
+ hs << " " << type << " " << getter << "() const;\n";
cs << type << " "
- << className << "::" << getter << "() const" << Qt::endl
- << "{" << Qt::endl
- << " // get the value of property " << property.name << Qt::endl
- << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl
- << "}" << Qt::endl
- << Qt::endl;
+ << className << "::" << getter << "() const\n"
+ "{\n"
+ " // get the value of property " << property.name << "\n"
+ " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));\n"
+ "}\n\n";
}
// setter
if (property.access != QDBusIntrospection::Property::Read) {
- hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl;
- cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl
- << "{" << Qt::endl
- << " // set the value of property " << property.name << Qt::endl
- << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value";
- if (constRefType.contains(QLatin1String("QDBusVariant")))
+ hs << " void " << setter << "(" << constRefType << "value);\n";
+ cs << "void " << className << "::" << setter << "(" << constRefType << "value)\n"
+ "{\n"
+ " // set the value of property " << property.name << "\n"
+ " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value";
+ if (constRefType.contains("QDBusVariant"_L1))
cs << ".variant()";
- cs << "));" << Qt::endl
- << "}" << Qt::endl
- << Qt::endl;
+ cs << "));\n"
+ "}\n\n";
}
- hs << Qt::endl;
+ hs << "\n";
}
- hs << "public Q_SLOTS: // METHODS" << Qt::endl;
+ hs << "public Q_SLOTS: // METHODS\n";
for (const QDBusIntrospection::Method &method : interface->methods) {
- bool isNoReply =
- method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true");
+ bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1;
if (isNoReply && !method.outputArgs.isEmpty()) {
- fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n",
- PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), qPrintable(interface->name));
+ reporter.warning(method.location,
+ "method %s in interface %s is marked 'no-reply' but has output "
+ "arguments.\n",
+ qPrintable(method.name), qPrintable(interface->name));
continue;
}
hs << " ";
- if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
- QLatin1String("true"))
- hs << "Q_DECL_DEPRECATED ";
-
QByteArray returnType;
if (isNoReply) {
hs << "Q_NOREPLY void ";
@@ -922,7 +1037,9 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
hs << "void ";
cs << "void ";
} else {
- returnType = qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out");
+ returnType =
+ qtTypeName(method.outputArgs.first().location,
+ method.outputArgs.first().type, method.annotations, 0, "Out");
hs << returnType << " ";
cs << returnType << " ";
}
@@ -935,46 +1052,42 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs);
- hs << ");" << Qt::endl; // finished for header
- cs << ")" << Qt::endl
- << "{" << Qt::endl
- << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl;
+ hs << ");\n"; // finished for header
+ cs << ")\n"
+ "{\n"
+ " // handle method call " << interface->name << "." << methodName(method) << "\n";
// make the call
bool usingInvokeMethod = false;
- if (parentClassName.isEmpty() && method.inputArgs.count() <= 10
- && method.outputArgs.count() <= 1)
+ if (parentClassName.isEmpty() && method.inputArgs.size() <= 10
+ && method.outputArgs.size() <= 1)
usingInvokeMethod = true;
if (usingInvokeMethod) {
// we are using QMetaObject::invokeMethod
if (!returnType.isEmpty())
- cs << " " << returnType << " " << argNames.at(method.inputArgs.count())
- << ";" << Qt::endl;
+ cs << " " << returnType << " " << argNames.at(method.inputArgs.size())
+ << ";\n";
static const char invoke[] = " QMetaObject::invokeMethod(parent(), \"";
cs << invoke << name << "\"";
if (!method.outputArgs.isEmpty())
cs << ", Q_RETURN_ARG("
- << qtTypeName(method.outputArgs.at(0).type, method.annotations,
- 0, "Out")
- << ", "
- << argNames.at(method.inputArgs.count())
- << ")";
+ << qtTypeName(method.outputArgs.at(0).location, method.outputArgs.at(0).type,
+ method.annotations, 0, "Out")
+ << ", " << argNames.at(method.inputArgs.size()) << ")";
- for (int i = 0; i < method.inputArgs.count(); ++i)
+ for (qsizetype i = 0; i < method.inputArgs.size(); ++i)
cs << ", Q_ARG("
- << qtTypeName(method.inputArgs.at(i).type, method.annotations,
- i, "In")
- << ", "
- << argNames.at(i)
- << ")";
+ << qtTypeName(method.inputArgs.at(i).location, method.inputArgs.at(i).type,
+ method.annotations, i, "In")
+ << ", " << argNames.at(i) << ")";
- cs << ");" << Qt::endl;
+ cs << ");\n";
if (!returnType.isEmpty())
- cs << " return " << argNames.at(method.inputArgs.count()) << ";" << Qt::endl;
+ cs << " return " << argNames.at(method.inputArgs.size()) << ";\n";
} else {
if (parentClassName.isEmpty())
cs << " //";
@@ -990,51 +1103,44 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
cs << "parent()->";
cs << name << "(";
- int argPos = 0;
+ qsizetype argPos = 0;
bool first = true;
- for (int i = 0; i < method.inputArgs.count(); ++i) {
+ for (qsizetype i = 0; i < method.inputArgs.size(); ++i) {
cs << (first ? "" : ", ") << argNames.at(argPos++);
first = false;
}
++argPos; // skip retval, if any
- for (int i = 1; i < method.outputArgs.count(); ++i) {
+ for (qsizetype i = 1; i < method.outputArgs.size(); ++i) {
cs << (first ? "" : ", ") << argNames.at(argPos++);
first = false;
}
- cs << ");" << Qt::endl;
+ cs << ");\n";
}
- cs << "}" << Qt::endl
- << Qt::endl;
+ cs << "}\n\n";
}
- hs << "Q_SIGNALS: // SIGNALS" << Qt::endl;
+ hs << "Q_SIGNALS: // SIGNALS\n";
for (const QDBusIntrospection::Signal &signal : interface->signals_) {
- hs << " ";
- if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
- QLatin1String("true"))
- hs << "Q_DECL_DEPRECATED ";
-
- hs << "void " << signal.name << "(";
+ hs << " void " << signal.name << "(";
QStringList argNames = makeArgNames(signal.outputArgs);
writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs);
- hs << ");" << Qt::endl; // finished for header
+ hs << ");\n"; // finished for header
}
// close the class:
- hs << "};" << Qt::endl
- << Qt::endl;
+ hs << "};\n\n";
}
// close the include guard
- hs << "#endif" << Qt::endl;
+ hs << "#endif\n";
QString mocName = moc(filename);
if (includeMocs && !mocName.isEmpty())
- cs << Qt::endl
- << "#include \"" << mocName << "\"" << Qt::endl;
+ cs << "\n"
+ "#include \"" << mocName << "\"\n";
cs.flush();
hs.flush();
@@ -1054,70 +1160,73 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
}
}
-int main(int argc, char **argv)
+int QDBusXmlToCpp::run(const QCoreApplication &app)
{
- QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationName(QStringLiteral(PROGRAMNAME));
- QCoreApplication::setApplicationVersion(QStringLiteral(PROGRAMVERSION));
-
QCommandLineParser parser;
- parser.setApplicationDescription(QLatin1String(
+ parser.setApplicationDescription(
"Produces the C++ code to implement the interfaces defined in the input file.\n\n"
"If the file name given to the options -a and -p does not end in .cpp or .h, the\n"
"program will automatically append the suffixes and produce both files.\n"
"You can also use a colon (:) to separate the header name from the source file\n"
"name, as in '-a filename_p.h:filename.cpp'.\n\n"
"If you pass a dash (-) as the argument to either -p or -a, the output is written\n"
- "to the standard output."));
+ "to the standard output."_L1);
parser.addHelpOption();
parser.addVersionOption();
- parser.addPositionalArgument(QStringLiteral("xml-or-xml-file"), QStringLiteral("XML file to use."));
- parser.addPositionalArgument(QStringLiteral("interfaces"), QStringLiteral("List of interfaces to use."),
- QStringLiteral("[interfaces ...]"));
+ parser.addPositionalArgument(u"xml-or-xml-file"_s, u"XML file to use."_s);
+ parser.addPositionalArgument(u"interfaces"_s, u"List of interfaces to use."_s,
+ u"[interfaces ...]"_s);
- QCommandLineOption adapterCodeOption(QStringList() << QStringLiteral("a") << QStringLiteral("adaptor"),
- QStringLiteral("Write the adaptor code to <filename>"), QStringLiteral("filename"));
+ QCommandLineOption adapterCodeOption(QStringList{u"a"_s, u"adaptor"_s},
+ u"Write the adaptor code to <filename>"_s, u"filename"_s);
parser.addOption(adapterCodeOption);
- QCommandLineOption classNameOption(QStringList() << QStringLiteral("c") << QStringLiteral("classname"),
- QStringLiteral("Use <classname> as the class name for the generated classes"), QStringLiteral("classname"));
+ QCommandLineOption classNameOption(QStringList{u"c"_s, u"classname"_s},
+ u"Use <classname> as the class name for the generated classes. "
+ u"This option can only be used when processing a single interface."_s,
+ u"classname"_s);
parser.addOption(classNameOption);
- QCommandLineOption addIncludeOption(QStringList() << QStringLiteral("i") << QStringLiteral("include"),
- QStringLiteral("Add #include to the output"), QStringLiteral("filename"));
+ QCommandLineOption addIncludeOption(QStringList{u"i"_s, u"include"_s},
+ u"Add #include \"filename\" to the output"_s, u"filename"_s);
parser.addOption(addIncludeOption);
- QCommandLineOption adapterParentOption(QStringLiteral("l"),
- QStringLiteral("When generating an adaptor, use <classname> as the parent class"), QStringLiteral("classname"));
+ QCommandLineOption addGlobalIncludeOption(QStringList{u"I"_s, u"global-include"_s},
+ u"Add #include <filename> to the output"_s, u"filename"_s);
+ parser.addOption(addGlobalIncludeOption);
+
+ QCommandLineOption adapterParentOption(u"l"_s,
+ u"When generating an adaptor, use <classname> as the parent class"_s, u"classname"_s);
parser.addOption(adapterParentOption);
- QCommandLineOption mocIncludeOption(QStringList() << QStringLiteral("m") << QStringLiteral("moc"),
- QStringLiteral("Generate #include \"filename.moc\" statements in the .cpp files"));
+ QCommandLineOption mocIncludeOption(QStringList{u"m"_s, u"moc"_s},
+ u"Generate #include \"filename.moc\" statements in the .cpp files"_s);
parser.addOption(mocIncludeOption);
- QCommandLineOption noNamespaceOption(QStringList() << QStringLiteral("N") << QStringLiteral("no-namespaces"),
- QStringLiteral("Don't use namespaces"));
+ QCommandLineOption noNamespaceOption(QStringList{u"N"_s, u"no-namespaces"_s},
+ u"Don't use namespaces"_s);
parser.addOption(noNamespaceOption);
- QCommandLineOption proxyCodeOption(QStringList() << QStringLiteral("p") << QStringLiteral("proxy"),
- QStringLiteral("Write the proxy code to <filename>"), QStringLiteral("filename"));
+ QCommandLineOption proxyCodeOption(QStringList{u"p"_s, u"proxy"_s},
+ u"Write the proxy code to <filename>"_s, u"filename"_s);
parser.addOption(proxyCodeOption);
- QCommandLineOption verboseOption(QStringList() << QStringLiteral("V") << QStringLiteral("verbose"),
- QStringLiteral("Be verbose."));
+ QCommandLineOption verboseOption(QStringList{u"V"_s, u"verbose"_s},
+ u"Be verbose."_s);
parser.addOption(verboseOption);
parser.process(app);
- adaptorFile = parser.value(adapterCodeOption);
+ QString adaptorFile = parser.value(adapterCodeOption);
globalClassName = parser.value(classNameOption);
includes = parser.values(addIncludeOption);
+ globalIncludes = parser.values(addGlobalIncludeOption);
parentClassName = parser.value(adapterParentOption);
includeMocs = parser.isSet(mocIncludeOption);
skipNamespaces = parser.isSet(noNamespaceOption);
- proxyFile = parser.value(proxyCodeOption);
- verbose = parser.isSet(verboseOption);
+ QString proxyFile = parser.value(proxyCodeOption);
+ bool verbose = parser.isSet(verboseOption);
wantedInterfaces = parser.positionalArguments();
if (!wantedInterfaces.isEmpty()) {
@@ -1131,15 +1240,19 @@ int main(int argc, char **argv)
}
if (verbose)
- QLoggingCategory::setFilterRules(QStringLiteral("dbus.parser.debug=true"));
+ QLoggingCategory::setFilterRules(u"dbus.parser.debug=true"_s);
QDBusIntrospection::Interfaces interfaces = readInput();
cleanInterfaces(interfaces);
+ if (!globalClassName.isEmpty() && interfaces.count() != 1) {
+ qCritical("Option -c/--classname can only be used with a single interface.\n");
+ return 1;
+ }
+
QStringList args = app.arguments();
args.removeFirst();
- commandLine = QLatin1String(PROGRAMNAME " ");
- commandLine += args.join(QLatin1Char(' '));
+ commandLine = PROGRAMNAME " "_L1 + args.join(u' ');
if (!proxyFile.isEmpty() || adaptorFile.isEmpty())
writeProxy(proxyFile, interfaces);
@@ -1150,3 +1263,11 @@ int main(int argc, char **argv)
return 0;
}
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationName(QStringLiteral(PROGRAMNAME));
+ QCoreApplication::setApplicationVersion(QStringLiteral(PROGRAMVERSION));
+
+ return QDBusXmlToCpp().run(app);
+}
diff --git a/src/tools/qlalr/CMakeLists.txt b/src/tools/qlalr/CMakeLists.txt
index 6feb2f9100..da8b351889 100644
--- a/src/tools/qlalr/CMakeLists.txt
+++ b/src/tools/qlalr/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from qlalr.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## qlalr Tool:
@@ -8,7 +9,7 @@ qt_get_tool_target_name(target_name qlalr)
qt_internal_add_tool(${target_name}
TARGET_DESCRIPTION "Qt Look Ahead LR Parser Generator"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
compress.cpp compress.h
cppgenerator.cpp cppgenerator.h
@@ -20,12 +21,10 @@ qt_internal_add_tool(${target_name}
recognizer.cpp recognizer.h
DEFINES
QT_NO_FOREACH
- PUBLIC_LIBRARIES
- Qt::Core # special case
+ QT_NO_QPAIR
+ QT_USE_NODISCARD_FILE_OPEN
+ LIBRARIES
+ Qt::Core
+ Qt::CorePrivate
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:qlalr.pro:<TRUE>:
-# OTHER_FILES = "lalr.g"
-# QMAKE_TARGET_DESCRIPTION = "Qt Look Ahead LR Parser Generator"
-# _OPTION = "host_build"
diff --git a/src/tools/qlalr/compress.cpp b/src/tools/qlalr/compress.cpp
index 054766671f..6ee083f7e9 100644
--- a/src/tools/qlalr/compress.cpp
+++ b/src/tools/qlalr/compress.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "compress.h"
@@ -164,7 +139,7 @@ void Compress::operator () (int *table, int row_count, int column_count)
#ifndef QLALR_NO_CHECK_SORTED_TABLE
int previous_zeros = INT_MAX;
- for (const UncompressedRow &row : qAsConst(sortedTable))
+ for (const UncompressedRow &row : std::as_const(sortedTable))
{
int zeros = row.count (0);
@@ -176,7 +151,7 @@ void Compress::operator () (int *table, int row_count, int column_count)
index.fill (-999999, row_count);
- for (const UncompressedRow &row : qAsConst(sortedTable))
+ for (const UncompressedRow &row : std::as_const(sortedTable))
{
int first_token = std::distance (row.begin (), row.beginNonZeros ());
QList<int>::iterator pos = info.begin();
@@ -251,7 +226,7 @@ void Compress::operator () (int *table, int row_count, int column_count)
}
#if 0
- for (const UncompressedRow &row : qAsConst(sortedTable))
+ for (const UncompressedRow &row : std::as_const(sortedTable))
{
int i = row.index ();
Q_ASSERT (i < sortedTable.size ());
diff --git a/src/tools/qlalr/compress.h b/src/tools/qlalr/compress.h
index 84b804e234..99f790348a 100644
--- a/src/tools/qlalr/compress.h
+++ b/src/tools/qlalr/compress.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef COMPRESS_H
#define COMPRESS_H
diff --git a/src/tools/qlalr/cppgenerator.cpp b/src/tools/qlalr/cppgenerator.cpp
index 7efe94a5c2..fd56de106d 100644
--- a/src/tools/qlalr/cppgenerator.cpp
+++ b/src/tools/qlalr/cppgenerator.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppgenerator.h"
@@ -35,9 +10,12 @@
#include <QtCore/qtextstream.h>
#include <QtCore/qfile.h>
#include <QtCore/qmap.h>
+#include <QtCore/private/qconfig_p.h>
#include <iterator>
+using namespace Qt::StringLiterals;
+
namespace {
void generateSeparator(int i, QTextStream &out)
@@ -64,40 +42,15 @@ void generateList(const QList<int> &list, QTextStream &out)
QString CppGenerator::copyrightHeader() const
{
- return QLatin1String(
- "/****************************************************************************\n"
- "**\n"
- "** Copyright (C) 2016 The Qt Company Ltd.\n"
- "** Contact: https://www.qt.io/licensing/\n"
- "**\n"
- "** This file is part of the Qt Toolkit.\n"
- "**\n"
- "** $QT_BEGIN_LICENSE:GPL-EXCEPT$\n"
- "** Commercial License Usage\n"
- "** Licensees holding valid commercial Qt licenses may use this file in\n"
- "** accordance with the commercial license agreement provided with the\n"
- "** Software or, alternatively, in accordance with the terms contained in\n"
- "** a written agreement between you and The Qt Company. For licensing terms\n"
- "** and conditions see https://www.qt.io/terms-conditions. For further\n"
- "** information use the contact form at https://www.qt.io/contact-us.\n"
- "**\n"
- "** GNU General Public License Usage\n"
- "** Alternatively, this file may be used under the terms of the GNU\n"
- "** General Public License version 3 as published by the Free Software\n"
- "** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT\n"
- "** included in the packaging of this file. Please review the following\n"
- "** information to ensure the GNU General Public License requirements will\n"
- "** be met: https://www.gnu.org/licenses/gpl-3.0.html.\n"
- "**\n"
- "** $QT_END_LICENSE$\n"
- "**\n"
- "****************************************************************************/\n"
- "\n");
+ return
+ "// " QT_COPYRIGHT "\n"
+ "// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0\n"
+ "\n"_L1;
}
QString CppGenerator::privateCopyrightHeader() const
{
- return QLatin1String(
+ return
"//\n"
"// W A R N I N G\n"
"// -------------\n"
@@ -107,12 +60,12 @@ QString CppGenerator::privateCopyrightHeader() const
"// version without notice, or even be removed.\n"
"//\n"
"// We mean it.\n"
- "//\n");
+ "//\n"_L1;
}
QString CppGenerator::startIncludeGuard(const QString &fileName)
{
- const QString normalized(QString(fileName).replace(QLatin1Char('.'), QLatin1Char('_')).toUpper());
+ const QString normalized(QString(fileName).replace(u'.', u'_').toUpper());
return QString::fromLatin1("#ifndef %1\n"
"#define %2\n").arg(normalized, normalized);
@@ -120,7 +73,7 @@ QString CppGenerator::startIncludeGuard(const QString &fileName)
QString CppGenerator::endIncludeGuard(const QString &fileName)
{
- const QString normalized(QString(fileName).replace(QLatin1Char('.'), QLatin1Char('_')).toUpper());
+ const QString normalized(QString(fileName).replace(u'.', u'_').toUpper());
return QString::fromLatin1("#endif // %1\n").arg(normalized);
}
@@ -240,7 +193,15 @@ void CppGenerator::operator () ()
{
if (shift_reduce_conflict_count != grammar.expected_shift_reduce
|| reduce_reduce_conflict_count != grammar.expected_reduce_reduce)
- qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl;
+ {
+ qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl;
+ if (warnings_are_errors)
+ {
+ qerr() << "qlalr: error: warning occurred, treating as error due to "
+ "--exit-on-warn." << Qt::endl;
+ exit(2);
+ }
+ }
if (verbose)
qout() << Qt::endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl
@@ -262,12 +223,20 @@ void CppGenerator::operator () ()
}
auto rule = grammar.rules.begin();
- for (int i = 0; i < used_rules.count (); ++i, ++rule)
+ for (int i = 0; i < used_rules.size(); ++i, ++rule)
{
if (! used_rules.testBit (i))
{
if (rule != grammar.goal)
- qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl;
+ {
+ qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl;
+ if (warnings_are_errors)
+ {
+ qerr() << "qlalr: error: warning occurred, treating as error due to "
+ "--exit-on-warn." << Qt::endl;
+ exit(2);
+ }
+ }
}
}
@@ -374,12 +343,17 @@ void CppGenerator::operator () ()
}
// default behaviour
- QString declFileName = grammar.table_name.toLower () + QLatin1String("_p.h");
- QString bitsFileName = grammar.table_name.toLower () + QLatin1String(".cpp");
+ QString declFileName = grammar.table_name.toLower () + "_p.h"_L1;
+ QString bitsFileName = grammar.table_name.toLower () + ".cpp"_L1;
{ // decls...
QFile f (declFileName);
- f.open (QFile::WriteOnly);
+ if (! f.open (QFile::WriteOnly))
+ {
+ fprintf (stderr, "*** cannot create %s: %s\n",
+ qPrintable(declFileName), qPrintable(f.errorString()));
+ return;
+ }
QTextStream out (&f);
QString prot = declFileName.toUpper ().replace (QLatin1Char ('.'), QLatin1Char ('_'));
@@ -411,7 +385,12 @@ void CppGenerator::operator () ()
{ // bits...
QFile f (bitsFileName);
- f.open (QFile::WriteOnly);
+ if (! f.open (QFile::WriteOnly))
+ {
+ fprintf (stderr, "*** cannot create %s: %s\n",
+ qPrintable(bitsFileName), qPrintable(f.errorString()));
+ return;
+ }
QTextStream out (&f);
// copyright headers must come first, otherwise the headers tests will fail
@@ -432,7 +411,12 @@ void CppGenerator::operator () ()
if (! grammar.decl_file_name.isEmpty ())
{
QFile f (grammar.decl_file_name);
- f.open (QFile::WriteOnly);
+ if (! f.open (QFile::WriteOnly))
+ {
+ fprintf (stderr, "*** cannot create %s: %s\n",
+ qPrintable(grammar.decl_file_name), qPrintable(f.errorString()));
+ return;
+ }
QTextStream out (&f);
out << p.decls();
}
@@ -440,7 +424,12 @@ void CppGenerator::operator () ()
if (! grammar.impl_file_name.isEmpty ())
{
QFile f (grammar.impl_file_name);
- f.open (QFile::WriteOnly);
+ if (! f.open (QFile::WriteOnly))
+ {
+ fprintf (stderr, "*** cannot create %s: %s\n",
+ qPrintable(grammar.impl_file_name), qPrintable(f.errorString()));
+ return;
+ }
QTextStream out (&f);
out << p.impls();
}
@@ -448,9 +437,9 @@ void CppGenerator::operator () ()
QString CppGenerator::debugInfoProt() const
{
- QString prot = QLatin1String("QLALR_NO_");
+ QString prot = "QLALR_NO_"_L1;
prot += grammar.table_name.toUpper();
- prot += QLatin1String("_DEBUG_INFO");
+ prot += "_DEBUG_INFO"_L1;
return prot;
}
@@ -461,16 +450,16 @@ void CppGenerator::generateDecl (QTextStream &out)
<< "public:" << Qt::endl
<< " enum VariousConstants {" << Qt::endl;
- for (const Name &t : qAsConst(grammar.terminals))
+ for (const Name &t : std::as_const(grammar.terminals))
{
QString name = *t;
int value = std::distance (grammar.names.begin (), t);
- if (name == QLatin1String ("$end"))
- name = QLatin1String ("EOF_SYMBOL");
+ if (name == "$end"_L1)
+ name = "EOF_SYMBOL"_L1;
- else if (name == QLatin1String ("$accept"))
- name = QLatin1String ("ACCEPT_SYMBOL");
+ else if (name == "$accept"_L1)
+ name = "ACCEPT_SYMBOL"_L1;
else
name.prepend (grammar.token_prefix);
diff --git a/src/tools/qlalr/cppgenerator.h b/src/tools/qlalr/cppgenerator.h
index a83ec101fd..66ae781be4 100644
--- a/src/tools/qlalr/cppgenerator.h
+++ b/src/tools/qlalr/cppgenerator.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CPPGENERATOR_H
#define CPPGENERATOR_H
@@ -45,7 +20,8 @@ public:
aut (aut),
verbose (verbose),
debug_info (false),
- copyright (false) {}
+ copyright (false),
+ warnings_are_errors(false) {}
void operator () ();
@@ -54,6 +30,8 @@ public:
void setCopyright (bool t) { copyright = t; }
+ void setWarningsAreErrors (bool e) { warnings_are_errors = e; }
+
private:
void generateDecl (QTextStream &out);
void generateImpl (QTextStream &out);
@@ -76,6 +54,7 @@ private:
int non_terminal_count;
bool debug_info;
bool copyright;
+ bool warnings_are_errors;
Compress compressed_action;
Compress compressed_goto;
QList<int> count;
diff --git a/src/tools/qlalr/dotgraph.cpp b/src/tools/qlalr/dotgraph.cpp
index 1d479af2b2..75bd304367 100644
--- a/src/tools/qlalr/dotgraph.cpp
+++ b/src/tools/qlalr/dotgraph.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "dotgraph.h"
diff --git a/src/tools/qlalr/dotgraph.h b/src/tools/qlalr/dotgraph.h
index 2d4f1cd2fc..42d4527c46 100644
--- a/src/tools/qlalr/dotgraph.h
+++ b/src/tools/qlalr/dotgraph.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef DOTGRAPH_H
#define DOTGRAPH_H
diff --git a/src/tools/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp b/src/tools/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp
index 7bf1506b4a..24399d3786 100644
--- a/src/tools/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp
+++ b/src/tools/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <cstdlib>
#include <cstdio>
diff --git a/src/tools/qlalr/examples/dummy-xml/xml.g b/src/tools/qlalr/examples/dummy-xml/xml.g
index 43c1fb169f..59472dc219 100644
--- a/src/tools/qlalr/examples/dummy-xml/xml.g
+++ b/src/tools/qlalr/examples/dummy-xml/xml.g
@@ -1,30 +1,5 @@
-----------------------------------------------------------------------------
---
-- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QtCore module 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$
---
-----------------------------------------------------------------------------
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
%parser XMLTable
diff --git a/src/tools/qlalr/examples/glsl/build.sh b/src/tools/qlalr/examples/glsl/build.sh
index 5bd0faab07..d43889bf72 100644
--- a/src/tools/qlalr/examples/glsl/build.sh
+++ b/src/tools/qlalr/examples/glsl/build.sh
@@ -1,31 +1,6 @@
#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility 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 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
${FLEX-flex} -oglsl-lex.incl glsl-lex.l
${QLALR-qlalr} glsl.g
diff --git a/src/tools/qlalr/examples/glsl/glsl-lex.l b/src/tools/qlalr/examples/glsl/glsl-lex.l
index c92aad296b..f3f9bb4f50 100644
--- a/src/tools/qlalr/examples/glsl/glsl-lex.l
+++ b/src/tools/qlalr/examples/glsl/glsl-lex.l
@@ -1,32 +1,5 @@
-
-%{
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR tool 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <cassert>
#define YY_DECL int GLSLParser::nextToken()
diff --git a/src/tools/qlalr/examples/glsl/glsl.g b/src/tools/qlalr/examples/glsl/glsl.g
index 66a2c73656..223e90284d 100644
--- a/src/tools/qlalr/examples/glsl/glsl.g
+++ b/src/tools/qlalr/examples/glsl/glsl.g
@@ -1,30 +1,5 @@
-----------------------------------------------------------------------------
---
-- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QtCore module 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$
---
-----------------------------------------------------------------------------
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
%parser GLSLParserTable
%merged_output glsl.cpp
diff --git a/src/tools/qlalr/examples/lambda/lambda.g b/src/tools/qlalr/examples/lambda/lambda.g
index 2aa3c128e9..d4fd01ed4c 100644
--- a/src/tools/qlalr/examples/lambda/lambda.g
+++ b/src/tools/qlalr/examples/lambda/lambda.g
@@ -1,30 +1,5 @@
-----------------------------------------------------------------------------
---
-- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QtCore module 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$
---
-----------------------------------------------------------------------------
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-- lambda calculus
diff --git a/src/tools/qlalr/examples/lambda/main.cpp b/src/tools/qlalr/examples/lambda/main.cpp
index 6198cc8538..c6a2695493 100644
--- a/src/tools/qlalr/examples/lambda/main.cpp
+++ b/src/tools/qlalr/examples/lambda/main.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "lambda.h"
diff --git a/src/tools/qlalr/examples/qparser/calc.g b/src/tools/qlalr/examples/qparser/calc.g
index 8524c1ca2c..2be9fd55c0 100644
--- a/src/tools/qlalr/examples/qparser/calc.g
+++ b/src/tools/qlalr/examples/qparser/calc.g
@@ -1,30 +1,5 @@
-----------------------------------------------------------------------------
---
-- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QtCore module 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$
---
-----------------------------------------------------------------------------
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
%parser calc_grammar
%decl calc_parser.h
diff --git a/src/tools/qlalr/examples/qparser/calc.l b/src/tools/qlalr/examples/qparser/calc.l
index fe542680a8..0f42987758 100644
--- a/src/tools/qlalr/examples/qparser/calc.l
+++ b/src/tools/qlalr/examples/qparser/calc.l
@@ -1,34 +1,5 @@
-
-%option noyywrap
-
-%{
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR tool 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "calc_parser.h"
#include <cstdlib>
diff --git a/src/tools/qlalr/examples/qparser/qparser.cpp b/src/tools/qlalr/examples/qparser/qparser.cpp
index c173436a9c..354a778458 100644
--- a/src/tools/qlalr/examples/qparser/qparser.cpp
+++ b/src/tools/qlalr/examples/qparser/qparser.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "qparser.h"
diff --git a/src/tools/qlalr/examples/qparser/qparser.h b/src/tools/qlalr/examples/qparser/qparser.h
index 7700562d55..80643616c4 100644
--- a/src/tools/qlalr/examples/qparser/qparser.h
+++ b/src/tools/qlalr/examples/qparser/qparser.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR module 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef QPARSER_H
#define QPARSER_H
diff --git a/src/tools/qlalr/grammar.cpp b/src/tools/qlalr/grammar.cpp
index 2ab6504bf8..d4d8916c6d 100644
--- a/src/tools/qlalr/grammar.cpp
+++ b/src/tools/qlalr/grammar.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// This file was generated by qlalr - DO NOT EDIT!
#include "grammar_p.h"
diff --git a/src/tools/qlalr/grammar_p.h b/src/tools/qlalr/grammar_p.h
index 8482f9bfe1..b6fa6b6353 100644
--- a/src/tools/qlalr/grammar_p.h
+++ b/src/tools/qlalr/grammar_p.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
//
// W A R N I N G
diff --git a/src/tools/qlalr/lalr.cpp b/src/tools/qlalr/lalr.cpp
index 853465c272..51f1d94a40 100644
--- a/src/tools/qlalr/lalr.cpp
+++ b/src/tools/qlalr/lalr.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "lalr.h"
@@ -39,6 +14,8 @@
#define QLALR_NO_DEBUG_INCLUDES
#define QLALR_NO_DEBUG_LOOKAHEADS
+using namespace Qt::StringLiterals;
+
QT_BEGIN_NAMESPACE
QTextStream &qerr()
{
@@ -162,24 +139,24 @@ State::State (Grammar *g):
{
}
-QPair<ItemPointer, bool> State::insert (const Item &item)
+std::pair<ItemPointer, bool> State::insert(const Item &item)
{
ItemPointer it = std::find (kernel.begin (), kernel.end (), item);
if (it != kernel.end ())
- return qMakePair (it, false);
+ return {it, false};
- return qMakePair (kernel.insert (it, item), true);
+ return {kernel.insert(it, item), true};
}
-QPair<ItemPointer, bool> State::insertClosure (const Item &item)
+std::pair<ItemPointer, bool> State::insertClosure(const Item &item)
{
ItemPointer it = std::find (closure.begin (), closure.end (), item);
if (it != closure.end ())
- return qMakePair (it, false);
+ return {it, false};
- return qMakePair (closure.insert (it, item), true);
+ return {closure.insert (it, item), true};
}
@@ -194,11 +171,11 @@ Grammar::Grammar ():
current_prec = 0;
current_assoc = NonAssoc;
- table_name = QLatin1String ("parser_table");
+ table_name = "parser_table"_L1;
tk_end = intern ("$end");
terminals.insert (tk_end);
- spells.insert (tk_end, QLatin1String("end of file"));
+ spells.insert (tk_end, "end of file"_L1);
/*tk_error= terminals.insert (intern ("error"))*/;
}
@@ -319,14 +296,14 @@ void Automaton::buildNullables ()
#endif
}
-QPair<StatePointer, bool> Automaton::internState (const State &state)
+std::pair<StatePointer, bool> Automaton::internState(const State &state)
{
StatePointer it = std::find (states.begin (), states.end (), state);
if (it != states.end ())
- return qMakePair (it, false);
+ return {it, false};
- return qMakePair (states.insert (it, state), true);
+ return {states.insert (it, state), true};
}
struct _Bucket
@@ -374,7 +351,7 @@ void Automaton::closure (StatePointer state)
if (_M_grammar->isNonTerminal (*item->dot))
{
- const auto range = qAsConst(_M_grammar->rule_map).equal_range(*item->dot);
+ const auto range = std::as_const(_M_grammar->rule_map).equal_range(*item->dot);
for (auto it = range.first; it != range.second; ++it)
{
const RulePointer &rule = *it;
@@ -382,7 +359,7 @@ void Automaton::closure (StatePointer state)
ii.rule = rule;
ii.dot = rule->rhs.begin ();
- QPair<ItemPointer, bool> r = state->insertClosure (ii);
+ std::pair<ItemPointer, bool> r = state->insertClosure(ii);
if (r.second)
working_list.push (r.first);
@@ -394,7 +371,7 @@ void Automaton::closure (StatePointer state)
for (bucket_map_type::iterator bucket = buckets.begin (); bucket != buckets.end (); ++bucket)
{
- QPair<StatePointer, bool> r = internState (bucket->toState (this));
+ std::pair<StatePointer, bool> r = internState(bucket->toState(this));
StatePointer target = r.first;
@@ -422,7 +399,7 @@ void Automaton::buildLookbackSets ()
if (! _M_grammar->isNonTerminal (A))
continue;
- const auto range = qAsConst(_M_grammar->rule_map).equal_range(A);
+ const auto range = std::as_const(_M_grammar->rule_map).equal_range(A);
for (auto it = range.first; it != range.second; ++it)
{
const RulePointer &rule = *it;
@@ -617,7 +594,7 @@ void Automaton::buildIncludesDigraph ()
if (! _M_grammar->isNonTerminal (name))
continue;
- const auto range = qAsConst(_M_grammar->rule_map).equal_range(name);
+ const auto range = std::as_const(_M_grammar->rule_map).equal_range(name);
for (auto it = range.first; it != range.second; ++it)
{
const RulePointer &rule = *it;
@@ -719,7 +696,7 @@ void Automaton::buildLookaheads ()
{
for (ItemPointer item = p->closure.begin (); item != p->closure.end (); ++item)
{
- const auto range = qAsConst(lookbacks).equal_range(item);
+ const auto range = std::as_const(lookbacks).equal_range(item);
for (auto it = range.first; it != range.second; ++it)
{
const Lookback &lookback = *it;
diff --git a/src/tools/qlalr/lalr.g b/src/tools/qlalr/lalr.g
index 3c1d1d3ebd..71d0054feb 100644
--- a/src/tools/qlalr/lalr.g
+++ b/src/tools/qlalr/lalr.g
@@ -1,30 +1,5 @@
------------------------------------------------------------------------------
---
-- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QLALR project on Qt Labs.
---
--- $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$
---
------------------------------------------------------------------------------
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
%parser grammar
@@ -61,33 +36,8 @@
%start Specification
-/:/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR project on Qt Labs.
-**
-** $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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "$header"
@@ -126,7 +76,7 @@ protected: // scanner
{
ch = *_M_currentChar++;
- if (ch == QLatin1Char('\n'))
+ if (ch == u'\n')
++_M_line;
}
else
@@ -162,33 +112,8 @@ protected:
};
:/
-/./****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR project on Qt Labs.
-**
-** $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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "recognizer.h"
@@ -198,6 +123,8 @@ protected:
#include <cstring>
#include <cctype>
+using namespace Qt::StringLiterals;
+
Recognizer::Recognizer (Grammar *grammar, bool no_lines):
tos(0),
stack_size(0),
@@ -247,9 +174,9 @@ int Recognizer::nextToken()
{
inp(); // skip "
text.clear ();
- while (! ch.isNull () && ch != QLatin1Char ('"'))
+ while (! ch.isNull () && ch != u'"')
{
- if (ch == QLatin1Char ('\\'))
+ if (ch == u'\\')
{
text += ch;
inp();
@@ -258,7 +185,7 @@ int Recognizer::nextToken()
inp ();
}
- if (ch == QLatin1Char ('"'))
+ if (ch == u'"')
inp ();
else
qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl;
@@ -267,11 +194,11 @@ int Recognizer::nextToken()
return (token = STRING_LITERAL);
}
- else if (ch.isLetterOrNumber () || ch == QLatin1Char ('_'))
+ else if (ch.isLetterOrNumber () || ch == u'_')
{
text.clear ();
do { text += ch; inp (); }
- while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('.'));
+ while (ch.isLetterOrNumber () || ch == u'_' || ch == u'.');
_M_current_value = text;
return (token = ID);
}
@@ -284,33 +211,33 @@ int Recognizer::nextToken()
while (ch.isSpace ());
do { text += ch; inp (); }
- while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('-'));
+ while (ch.isLetterOrNumber () || ch == u'_' || ch == u'-');
- if (text == QLatin1String("token_prefix"))
+ if (text == "token_prefix"_L1)
return (token = TOKEN_PREFIX);
- else if (text == QLatin1String("merged_output"))
+ else if (text == "merged_output"_L1)
return (token = MERGED_OUTPUT);
- else if (text == QLatin1String("token"))
+ else if (text == "token"_L1)
return (token = TOKEN);
- else if (text == QLatin1String("start"))
+ else if (text == "start"_L1)
return (token = START);
- else if (text == QLatin1String("parser"))
+ else if (text == "parser"_L1)
return (token = PARSER);
- else if (text == QLatin1String("decl"))
+ else if (text == "decl"_L1)
return (token = DECL_FILE);
- else if (text == QLatin1String("impl"))
+ else if (text == "impl"_L1)
return (token = IMPL_FILE);
- else if (text == QLatin1String("expect"))
+ else if (text == "expect"_L1)
return (token = EXPECT);
- else if (text == QLatin1String("expect-rr"))
+ else if (text == "expect-rr"_L1)
return (token = EXPECT_RR);
- else if (text == QLatin1String("left"))
+ else if (text == "left"_L1)
return (token = LEFT);
- else if (text == QLatin1String("right"))
+ else if (text == "right"_L1)
return (token = RIGHT);
- else if (text == QLatin1String("nonassoc"))
+ else if (text == "nonassoc"_L1)
return (token = NONASSOC);
- else if (text == QLatin1String("prec"))
+ else if (text == "prec"_L1)
return (token = PREC);
else
{
@@ -322,30 +249,30 @@ int Recognizer::nextToken()
inp ();
- if (token == '-' && ch == QLatin1Char ('-'))
+ if (token == '-' && ch == u'-')
{
do { inp (); }
- while (! ch.isNull () && ch != QLatin1Char ('\n'));
+ while (! ch.isNull () && ch != u'\n');
goto Lagain;
}
- else if (token == ':' && ch == QLatin1Char (':'))
+ else if (token == ':' && ch == u':')
{
inp ();
- if (ch != QLatin1Char ('='))
+ if (ch != u'=')
return (token = ERROR);
inp ();
return (token = COLON);
}
- else if (token == '/' && ch == QLatin1Char (':'))
+ else if (token == '/' && ch == u':')
{
_M_action_line = _M_line;
text.clear ();
if (! _M_no_lines)
- text += QLatin1String("\n#line ") + QString::number(_M_action_line) +
- QLatin1String(" \"") + QDir::fromNativeSeparators(_M_input_file) + QLatin1String("\"\n");
+ text += "\n#line "_L1 + QString::number(_M_action_line) +
+ " \""_L1 + QDir::fromNativeSeparators(_M_input_file) + "\"\n"_L1;
inp (); // skip ':'
forever
@@ -355,13 +282,13 @@ int Recognizer::nextToken()
token = ch.unicode ();
inp ();
- if (token == ':' && ch == QLatin1Char ('/'))
+ if (token == ':' && ch == u'/')
break;
text += QLatin1Char (token);
}
- if (ch != QLatin1Char ('/'))
+ if (ch != u'/')
return (token = ERROR);
inp ();
@@ -372,18 +299,18 @@ int Recognizer::nextToken()
return (token = DECL);
}
else
- text += QLatin1String (":/");
+ text += ":/"_L1;
}
}
- else if (token == '/' && ch == QLatin1Char ('.'))
+ else if (token == '/' && ch == u'.')
{
_M_action_line = _M_line;
text.clear ();
if (! _M_no_lines)
- text += QLatin1String("\n#line ") + QString::number(_M_action_line) +
- QLatin1String(" \"") + QDir::fromNativeSeparators(_M_input_file) + QLatin1String("\"\n");
+ text += "\n#line "_L1 + QString::number(_M_action_line) +
+ " \""_L1 + QDir::fromNativeSeparators(_M_input_file) + "\"\n"_L1;
inp (); // skip ':'
@@ -394,13 +321,13 @@ int Recognizer::nextToken()
token = ch.unicode ();
inp ();
- if (token == '.' && ch == QLatin1Char ('/'))
+ if (token == '.' && ch == u'/')
break;
text += QLatin1Char (token);
}
- if (ch != QLatin1Char ('/'))
+ if (ch != u'/')
return (token = ERROR);
inp ();
@@ -411,7 +338,7 @@ int Recognizer::nextToken()
return (token = IMPL);
}
else
- text += QLatin1String ("./");
+ text += "./"_L1;
}
}
diff --git a/src/tools/qlalr/lalr.h b/src/tools/qlalr/lalr.h
index 5be44fea67..efa0a91a39 100644
--- a/src/tools/qlalr/lalr.h
+++ b/src/tools/qlalr/lalr.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef LALR_H
#define LALR_H
@@ -34,7 +9,6 @@
#include <QtCore/qmap.h>
#include <QtCore/qstring.h>
#include <QtCore/qtextstream.h>
-#include <QtCore/qpair.h>
#include <algorithm>
#include <functional>
@@ -142,8 +116,8 @@ public:
inline bool operator != (const State &other) const
{ return kernel != other.kernel; }
- QPair<ItemPointer, bool> insert (const Item &item);
- QPair<ItemPointer, bool> insertClosure (const Item &item);
+ std::pair<ItemPointer, bool> insert(const Item &item);
+ std::pair<ItemPointer, bool> insertClosure(const Item &item);
public: // attributes
ItemList kernel;
@@ -168,7 +142,7 @@ public:
public:
static iterator get (_Tp data);
- QPair<edge_iterator, bool> insertEdge (iterator other) const;
+ std::pair<edge_iterator, bool> insertEdge(iterator other) const;
inline edge_iterator begin () const
{ return outs.begin (); }
@@ -223,15 +197,15 @@ typename Node<_Tp>::iterator Node<_Tp>::get (_Tp data)
}
template <typename _Tp>
-QPair<typename std::list<typename Node<_Tp>::iterator>::iterator, bool> Node<_Tp>::insertEdge(typename Node<_Tp>::iterator other) const
+std::pair<typename std::list<typename Node<_Tp>::iterator>::iterator, bool> Node<_Tp>::insertEdge(typename Node<_Tp>::iterator other) const
{
edge_iterator it = std::find (outs.begin (), outs.end (), other);
if (it != outs.end ())
- return qMakePair (it, false);
+ return {it, false};
other->root = false;
- return qMakePair (outs.insert (outs.end (), other), true);
+ return {outs.insert (outs.end (), other), true};
}
/////////////////////////////////////////////////////////////
@@ -337,7 +311,7 @@ class Automaton
public:
Automaton (Grammar *g);
- QPair<StatePointer, bool> internState (const State &state);
+ std::pair<StatePointer, bool> internState (const State &state);
typedef Node<Read> ReadsGraph;
typedef ReadsGraph::iterator ReadNode;
diff --git a/src/tools/qlalr/main.cpp b/src/tools/qlalr/main.cpp
index 6a57c7aa7a..04ae54d986 100644
--- a/src/tools/qlalr/main.cpp
+++ b/src/tools/qlalr/main.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "lalr.h"
#include "dotgraph.h"
@@ -42,6 +17,8 @@
#define QLALR_NO_DEBUG_TABLE
#define QLALR_NO_DEBUG_DOT
+using namespace Qt::StringLiterals;
+
static void help_me ()
{
qerr() << "Usage: qlalr [options] [input file name]" << Qt::endl
@@ -51,7 +28,8 @@ static void help_me ()
<< " --no-debug\t\tno debug information" << Qt::endl
<< " --no-lines\t\tno #line directives" << Qt::endl
<< " --dot\t\t\tgenerate a graph" << Qt::endl
- << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl
+ << " --qt\t\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl
+ << " --exit-on-warn\texit with status code 2 on warning" << Qt::endl
<< Qt::endl;
exit (0);
}
@@ -65,28 +43,32 @@ int main (int argc, char *argv[])
bool no_lines = false;
bool debug_info = true;
bool qt_copyright = false;
+ bool warnings_are_errors = false;
QString file_name;
const QStringList args = app.arguments().mid(1);
for (const QString &arg : args) {
- if (arg == QLatin1String ("-h") || arg == QLatin1String ("--help"))
+ if (arg == "-h"_L1 || arg == "--help"_L1)
help_me ();
- else if (arg == QLatin1String ("-v") || arg == QLatin1String ("--verbose"))
+ else if (arg == "-v"_L1 || arg == "--verbose"_L1)
generate_report = true;
- else if (arg == QLatin1String ("--dot"))
+ else if (arg == "--dot"_L1)
generate_dot = true;
- else if (arg == QLatin1String ("--no-lines"))
+ else if (arg == "--no-lines"_L1)
no_lines = true;
- else if (arg == QLatin1String ("--no-debug"))
+ else if (arg == "--no-debug"_L1)
debug_info = false;
- else if (arg == QLatin1String ("--qt"))
+ else if (arg == "--qt"_L1)
qt_copyright = true;
+ else if (arg == "--exit-on-warn"_L1)
+ warnings_are_errors = true;
+
else if (file_name.isEmpty ())
file_name = arg;
@@ -127,6 +109,7 @@ int main (int argc, char *argv[])
CppGenerator gen (p, grammar, aut, generate_report);
gen.setDebugInfo (debug_info);
gen.setCopyright (qt_copyright);
+ gen.setWarningsAreErrors (warnings_are_errors);
gen ();
if (generate_dot)
@@ -150,19 +133,19 @@ QString Recognizer::expand (const QString &text) const
if (_M_grammar->start != _M_grammar->names.end ())
{
- code = code.replace (QLatin1String("$start_id"), QString::number (std::distance (_M_grammar->names.begin (), _M_grammar->start)));
- code = code.replace (QLatin1String("$start"), *_M_grammar->start);
+ code = code.replace ("$start_id"_L1, QString::number (std::distance (_M_grammar->names.begin (), _M_grammar->start)));
+ code = code.replace ("$start"_L1, *_M_grammar->start);
}
- code = code.replace (QLatin1String("$header"), _M_grammar->table_name.toLower () + QLatin1String("_p.h"));
+ code = code.replace ("$header"_L1, _M_grammar->table_name.toLower () + "_p.h"_L1);
- code = code.replace (QLatin1String("$table"), _M_grammar->table_name);
- code = code.replace (QLatin1String("$parser"), _M_grammar->table_name);
+ code = code.replace ("$table"_L1, _M_grammar->table_name);
+ code = code.replace ("$parser"_L1, _M_grammar->table_name);
if (_M_current_rule != _M_grammar->rules.end ())
{
- code = code.replace (QLatin1String("$rule_number"), QString::number (std::distance (_M_grammar->rules.begin (), _M_current_rule)));
- code = code.replace (QLatin1String("$rule"), *_M_current_rule->lhs);
+ code = code.replace ("$rule_number"_L1, QString::number (std::distance (_M_grammar->rules.begin (), _M_current_rule)));
+ code = code.replace ("$rule"_L1, *_M_current_rule->lhs);
}
return code;
diff --git a/src/tools/qlalr/parsetable.cpp b/src/tools/qlalr/parsetable.cpp
index 9e71acebb4..c144b6f7a6 100644
--- a/src/tools/qlalr/parsetable.cpp
+++ b/src/tools/qlalr/parsetable.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "parsetable.h"
diff --git a/src/tools/qlalr/parsetable.h b/src/tools/qlalr/parsetable.h
index 2bf477011b..9d3a97026b 100644
--- a/src/tools/qlalr/parsetable.h
+++ b/src/tools/qlalr/parsetable.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the utils 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PARSETABLE_H
#define PARSETABLE_H
diff --git a/src/tools/qlalr/recognizer.cpp b/src/tools/qlalr/recognizer.cpp
index 760a094460..65862f7b02 100644
--- a/src/tools/qlalr/recognizer.cpp
+++ b/src/tools/qlalr/recognizer.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR project on Qt Labs.
-**
-** $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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "recognizer.h"
@@ -34,6 +9,8 @@
#include <cstring>
#include <cctype>
+using namespace Qt::StringLiterals;
+
Recognizer::Recognizer (Grammar *grammar, bool no_lines):
tos(0),
stack_size(0),
@@ -83,9 +60,9 @@ int Recognizer::nextToken()
{
inp(); // skip "
text.clear ();
- while (! ch.isNull () && ch != QLatin1Char ('"'))
+ while (!ch.isNull () && ch != u'"')
{
- if (ch == QLatin1Char ('\\'))
+ if (ch == u'\\')
{
text += ch;
inp();
@@ -94,7 +71,7 @@ int Recognizer::nextToken()
inp ();
}
- if (ch == QLatin1Char ('"'))
+ if (ch == u'"')
inp ();
else
qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl;
@@ -103,11 +80,11 @@ int Recognizer::nextToken()
return (token = STRING_LITERAL);
}
- else if (ch.isLetterOrNumber () || ch == QLatin1Char ('_'))
+ else if (ch.isLetterOrNumber () || ch == u'_')
{
text.clear ();
do { text += ch; inp (); }
- while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('.'));
+ while (ch.isLetterOrNumber () || ch == u'_' || ch == u'.');
_M_current_value = text;
return (token = ID);
}
@@ -120,33 +97,33 @@ int Recognizer::nextToken()
while (ch.isSpace ());
do { text += ch; inp (); }
- while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('-'));
+ while (ch.isLetterOrNumber () || ch == u'_' || ch == u'-');
- if (text == QLatin1String("token_prefix"))
+ if (text == "token_prefix"_L1)
return (token = TOKEN_PREFIX);
- else if (text == QLatin1String("merged_output"))
+ else if (text == "merged_output"_L1)
return (token = MERGED_OUTPUT);
- else if (text == QLatin1String("token"))
+ else if (text == "token"_L1)
return (token = TOKEN);
- else if (text == QLatin1String("start"))
+ else if (text == "start"_L1)
return (token = START);
- else if (text == QLatin1String("parser"))
+ else if (text == "parser"_L1)
return (token = PARSER);
- else if (text == QLatin1String("decl"))
+ else if (text == "decl"_L1)
return (token = DECL_FILE);
- else if (text == QLatin1String("impl"))
+ else if (text == "impl"_L1)
return (token = IMPL_FILE);
- else if (text == QLatin1String("expect"))
+ else if (text == "expect"_L1)
return (token = EXPECT);
- else if (text == QLatin1String("expect-rr"))
+ else if (text == "expect-rr"_L1)
return (token = EXPECT_RR);
- else if (text == QLatin1String("left"))
+ else if (text == "left"_L1)
return (token = LEFT);
- else if (text == QLatin1String("right"))
+ else if (text == "right"_L1)
return (token = RIGHT);
- else if (text == QLatin1String("nonassoc"))
+ else if (text == "nonassoc"_L1)
return (token = NONASSOC);
- else if (text == QLatin1String("prec"))
+ else if (text == "prec"_L1)
return (token = PREC);
else
{
@@ -158,30 +135,30 @@ int Recognizer::nextToken()
inp ();
- if (token == '-' && ch == QLatin1Char ('-'))
+ if (token == '-' && ch == u'-')
{
do { inp (); }
- while (! ch.isNull () && ch != QLatin1Char ('\n'));
+ while (!ch.isNull () && ch != u'\n');
goto Lagain;
}
- else if (token == ':' && ch == QLatin1Char (':'))
+ else if (token == ':' && ch == u':')
{
inp ();
- if (ch != QLatin1Char ('='))
+ if (ch != u'=')
return (token = ERROR);
inp ();
return (token = COLON);
}
- else if (token == '/' && ch == QLatin1Char (':'))
+ else if (token == '/' && ch == u':')
{
_M_action_line = _M_line;
text.clear ();
if (! _M_no_lines)
- text += QLatin1String("\n#line ") + QString::number(_M_action_line) +
- QLatin1String(" \"") + QDir::fromNativeSeparators(_M_input_file) + QLatin1String("\"\n");
+ text += "\n#line "_L1 + QString::number(_M_action_line) +
+ " \""_L1 + QDir::fromNativeSeparators(_M_input_file) + "\"\n"_L1;
inp (); // skip ':'
forever
@@ -191,13 +168,13 @@ int Recognizer::nextToken()
token = ch.unicode ();
inp ();
- if (token == ':' && ch == QLatin1Char ('/'))
+ if (token == ':' && ch == u'/')
break;
text += QLatin1Char (token);
}
- if (ch != QLatin1Char ('/'))
+ if (ch != u'/')
return (token = ERROR);
inp ();
@@ -208,18 +185,18 @@ int Recognizer::nextToken()
return (token = DECL);
}
else
- text += QLatin1String (":/");
+ text += ":/"_L1;
}
}
- else if (token == '/' && ch == QLatin1Char ('.'))
+ else if (token == '/' && ch == u'.')
{
_M_action_line = _M_line;
text.clear ();
if (! _M_no_lines)
- text += QLatin1String("\n#line ") + QString::number(_M_action_line) +
- QLatin1String(" \"") + QDir::fromNativeSeparators(_M_input_file) + QLatin1String("\"\n");
+ text += "\n#line "_L1 + QString::number(_M_action_line) +
+ " \""_L1 + QDir::fromNativeSeparators(_M_input_file) + "\"\n"_L1;
inp (); // skip ':'
@@ -230,13 +207,13 @@ int Recognizer::nextToken()
token = ch.unicode ();
inp ();
- if (token == '.' && ch == QLatin1Char ('/'))
+ if (token == '.' && ch == u'/')
break;
text += QLatin1Char (token);
}
- if (ch != QLatin1Char ('/'))
+ if (ch != u'/')
return (token = ERROR);
inp ();
@@ -247,7 +224,7 @@ int Recognizer::nextToken()
return (token = IMPL);
}
else
- text += QLatin1String ("");
+ text += ""_L1;
}
}
diff --git a/src/tools/qlalr/recognizer.h b/src/tools/qlalr/recognizer.h
index 001de3bcf1..31d606e657 100644
--- a/src/tools/qlalr/recognizer.h
+++ b/src/tools/qlalr/recognizer.h
@@ -1,30 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QLALR project on Qt Labs.
-**
-** $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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef RECOGNIZER_H
+#define RECOGNIZER_H
#include "grammar_p.h"
@@ -63,7 +41,7 @@ protected: // scanner
{
ch = *_M_currentChar++;
- if (ch == QLatin1Char('\n'))
+ if (ch == u'\n')
++_M_line;
}
else
@@ -97,3 +75,5 @@ protected:
QString _M_current_value;
bool _M_no_lines;
};
+
+#endif // RECOGNIZER_H
diff --git a/src/tools/qtpaths/CMakeLists.txt b/src/tools/qtpaths/CMakeLists.txt
index b7338f24ed..d64caeb3c2 100644
--- a/src/tools/qtpaths/CMakeLists.txt
+++ b/src/tools/qtpaths/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from qtpaths.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## qtpaths App:
@@ -6,13 +7,13 @@
qt_get_tool_target_name(target_name qtpaths)
qt_internal_add_tool(${target_name}
+ TRY_RUN
TARGET_DESCRIPTION "Qt tool that provides the standard paths of the Qt framework"
TOOLS_TARGET Core
INSTALL_VERSIONED_LINK
SOURCES
qtpaths.cpp
DEFINES
- QT_NO_FOREACH
QTPATHS_VERSION_STR="2.0"
)
qt_internal_return_unless_building_tools()
@@ -23,7 +24,6 @@ qt_internal_return_unless_building_tools()
qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_settings
LIBRARIES
QtLibraryInfo
- Qt::CorePrivate
)
if(WIN32 AND TARGET ${target_name})
diff --git a/src/tools/qtpaths/qtpaths.cpp b/src/tools/qtpaths/qtpaths.cpp
index f9643ad3fe..71f9fe4349 100644
--- a/src/tools/qtpaths/qtpaths.cpp
+++ b/src/tools/qtpaths/qtpaths.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
- * *
- ** Copyright (C) 2016 Sune Vuorela <sune@kde.org>
- ** Contact: http://www.qt-project.org/
- **
- ** This file is part of the tools applications of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:BSD$
- ** 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.
- **
- ** BSD License Usage
- ** Alternatively, you may use this file under the terms of the BSD license
- ** as follows:
- **
- ** "Redistribution and use in source and binary forms, with or without
- ** modification, are permitted provided that the following conditions are
- ** met:
- ** * Redistributions of source code must retain the above copyright
- ** notice, this list of conditions and the following disclaimer.
- ** * Redistributions in binary form must reproduce the above copyright
- ** notice, this list of conditions and the following disclaimer in
- ** the documentation and/or other materials provided with the
- ** distribution.
- ** * Neither the name of The Qt Company Ltd nor the names of its
- ** contributors may be used to endorse or promote products derived
- ** from this software without specific prior written permission.
- **
- **
- ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- **
- ** $QT_END_LICENSE$
- **
- ****************************************************************************/
+// Copyright (C) 2016 Sune Vuorela <sune@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QCoreApplication>
#include <QCommandLineParser>
@@ -108,9 +61,6 @@ static const StringEnum lookupTableData[] = {
{ "ApplicationsLocation", QStandardPaths::ApplicationsLocation, false },
{ "CacheLocation", QStandardPaths::CacheLocation, true },
{ "ConfigLocation", QStandardPaths::ConfigLocation, false },
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- { "DataLocation", QStandardPaths::DataLocation, true },
-#endif
{ "DesktopLocation", QStandardPaths::DesktopLocation, false },
{ "DocumentsLocation", QStandardPaths::DocumentsLocation, false },
{ "DownloadLocation", QStandardPaths::DownloadLocation, false },
@@ -118,12 +68,14 @@ static const StringEnum lookupTableData[] = {
{ "GenericCacheLocation", QStandardPaths::GenericCacheLocation, false },
{ "GenericConfigLocation", QStandardPaths::GenericConfigLocation, false },
{ "GenericDataLocation", QStandardPaths::GenericDataLocation, false },
+ { "GenericStateLocation", QStandardPaths::GenericStateLocation, false },
{ "HomeLocation", QStandardPaths::HomeLocation, false },
{ "MoviesLocation", QStandardPaths::MoviesLocation, false },
{ "MusicLocation", QStandardPaths::MusicLocation, false },
{ "PicturesLocation", QStandardPaths::PicturesLocation, false },
{ "PublicShareLocation", QStandardPaths::PublicShareLocation, false },
{ "RuntimeLocation", QStandardPaths::RuntimeLocation, false },
+ { "StateLocation", QStandardPaths::StateLocation, true },
{ "TemplatesLocation", QStandardPaths::TemplatesLocation, false },
{ "TempLocation", QStandardPaths::TempLocation, false }
};
@@ -147,7 +99,7 @@ static QStringList types()
static const StringEnum &parseLocationOrError(const QString &locationString)
{
for (const StringEnum &se : lookupTableData)
- if (locationString == QLatin1String(se.stringvalue))
+ if (locationString == QLatin1StringView(se.stringvalue))
return se;
QString message = QStringLiteral("Unknown location: %1");
@@ -170,6 +122,7 @@ static QString searchStringOrError(QCommandLineParser *parser)
int main(int argc, char **argv)
{
+ QString qtconfManualPath;
QCoreApplication app(argc, argv);
app.setApplicationVersion(QTPATHS_VERSION_STR);
@@ -267,13 +220,14 @@ int main(int argc, char **argv)
#if QT_CONFIG(settings)
if (parser.isSet(qtconf)) {
- QLibraryInfoPrivate::qtconfManualPath = parser.value(qtconf);
+ qtconfManualPath = parser.value(qtconf);
+ QLibraryInfoPrivate::setQtconfManualPath(&qtconfManualPath);
}
#endif
QStringList results;
if (parser.isSet(qtversion)) {
- QString qtversionstring = QString::fromLatin1(qVersion());
+ QString qtversionstring = QString::fromLatin1(QT_VERSION_STR);
results << qtversionstring;
}
@@ -297,6 +251,10 @@ int main(int argc, char **argv)
results << typesList.join('\n');
}
+ QT_WARNING_PUSH
+#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 1300 && Q_CC_GNU < 1500
+ QT_WARNING_DISABLE_GCC("-Wdangling-reference")
+#endif
if (parser.isSet(display)) {
const StringEnum &location = parseLocationOrError(parser.value(display));
QString text = QStandardPaths::displayName(location.enumvalue);
@@ -348,6 +306,7 @@ int main(int argc, char **argv)
QStringList paths = QStandardPaths::locateAll(location.enumvalue, searchitem, QStandardPaths::LocateFile);
results << location.mapName(paths.join(pathsep));
}
+ QT_WARNING_POP
#if !QT_CONFIG(settings)
if (parser.isSet(query) || parser.isSet(qtconf) || parser.isSet(queryformat)) {
@@ -385,7 +344,7 @@ int main(int argc, char **argv)
if (results.isEmpty()) {
parser.showHelp();
} else if (results.size() == 1) {
- const QString &item = results.first();
+ const QString &item = results.constFirst();
message(item);
if (item.isEmpty())
return EXIT_FAILURE;
diff --git a/src/tools/qvkgen/CMakeLists.txt b/src/tools/qvkgen/CMakeLists.txt
index 239dfb8c91..0f68968fd3 100644
--- a/src/tools/qvkgen/CMakeLists.txt
+++ b/src/tools/qvkgen/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from qvkgen.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## qvkgen Tool:
@@ -8,14 +9,10 @@ qt_get_tool_target_name(target_name qvkgen)
qt_internal_add_tool(${target_name}
TARGET_DESCRIPTION "Qt Vulkan Header Generator"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Gui # special case
+ TOOLS_TARGET Gui
SOURCES
qvkgen.cpp
- PUBLIC_LIBRARIES
- Qt::Core # special case
+ LIBRARIES
+ Qt::Core
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:qvkgen.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt Vulkan Header Generator"
-# _OPTION = "host_build"
diff --git a/src/tools/qvkgen/qvkgen.cpp b/src/tools/qvkgen/qvkgen.cpp
index 798cbb7932..3ef7aa56f6 100644
--- a/src/tools/qvkgen/qvkgen.cpp
+++ b/src/tools/qvkgen/qvkgen.cpp
@@ -1,42 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 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) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QtCore/qcoreapplication.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
#include <QtCore/qxmlstream.h>
// generate wrappers for core functions from the following versions
static const QStringList VERSIONS = {
QStringLiteral("VK_VERSION_1_0"), // must be the first and always present
QStringLiteral("VK_VERSION_1_1"),
- QStringLiteral("VK_VERSION_1_2")
+ QStringLiteral("VK_VERSION_1_2"),
+ QStringLiteral("VK_VERSION_1_3")
};
class VkSpecParser
@@ -234,11 +211,11 @@ VkSpecParser::TypedName VkSpecParser::parseParamOrProto(const QString &tag)
} else {
auto text = m_reader.text().trimmed();
if (!text.isEmpty()) {
- if (text.startsWith(QLatin1Char('['))) {
+ if (text.startsWith(u'[')) {
t.typeSuffix += text;
} else {
if (!t.type.isEmpty())
- t.type += QLatin1Char(' ');
+ t.type += u' ';
t.type += text;
}
}
@@ -266,7 +243,7 @@ QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr)
(className ? className : ""), (className ? "::" : ""),
qPrintable(c.cmd.name)));
if (!c.args.isEmpty()) {
- s += QLatin1Char('(');
+ s += u'(';
bool first = true;
for (const VkSpecParser::TypedName &a : c.args) {
if (!first)
@@ -274,10 +251,10 @@ QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr)
else
first = false;
s += QString::asprintf("%s%s%s%s", qPrintable(a.type),
- (a.type.endsWith(QLatin1Char('*')) ? "" : " "),
+ (a.type.endsWith(u'*') ? "" : " "),
qPrintable(a.name), qPrintable(a.typeSuffix));
}
- s += QLatin1Char(')');
+ s += u')';
}
return s;
}
@@ -291,7 +268,7 @@ QString funcCall(const VkSpecParser::Command &c, int idx)
qPrintable(c.cmd.name),
idx);
if (!c.args.isEmpty()) {
- s += QLatin1Char('(');
+ s += u'(';
bool first = true;
for (const VkSpecParser::TypedName &a : c.args) {
if (!first)
@@ -300,7 +277,7 @@ QString funcCall(const VkSpecParser::Command &c, int idx)
first = false;
s += a.name;
}
- s += QLatin1Char(')');
+ s += u')';
}
return s;
}
@@ -348,9 +325,13 @@ bool genVulkanFunctionsH(const QList<VkSpecParser::Command> &commands,
"#ifndef QVULKANFUNCTIONS_H\n"
"#define QVULKANFUNCTIONS_H\n"
"\n"
+"#if 0\n"
+"#pragma qt_no_master_include\n"
+"#endif\n"
+"\n"
"#include <QtGui/qtguiglobal.h>\n"
"\n"
-"#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)\n"
+"#if QT_CONFIG(vulkan) || defined(Q_QDOC)\n"
"\n"
"#ifndef VK_NO_PROTOTYPES\n"
"#define VK_NO_PROTOTYPES\n"
@@ -395,7 +376,7 @@ bool genVulkanFunctionsH(const QList<VkSpecParser::Command> &commands,
"\n"
"QT_END_NAMESPACE\n"
"\n"
-"#endif // QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)\n"
+"#endif // QT_CONFIG(vulkan) || defined(Q_QDOC)\n"
"\n"
"#endif // QVULKANFUNCTIONS_H\n";
@@ -509,22 +490,25 @@ bool genVulkanFunctionsPC(const QList<VkSpecParser::Command> &commands,
return false;
}
- static const char *s =
+ static const char s[] =
"%s\n"
"#include \"qvulkanfunctions_p.h\"\n"
"#include \"qvulkaninstance.h\"\n"
"\n"
+"#include <QtCore/private/qoffsetstringarray_p.h>\n"
+"\n"
"QT_BEGIN_NAMESPACE\n"
"\n%s"
"QVulkanFunctionsPrivate::QVulkanFunctionsPrivate(QVulkanInstance *inst)\n"
"{\n"
-" static const char *funcNames[] = {\n"
+" static constexpr auto funcNames = qOffsetStringArray(\n"
"%s\n"
-" };\n"
-" for (int i = 0; i < %d; ++i) {\n"
-" m_funcs[i] = inst->getInstanceProcAddr(funcNames[i]);\n"
+" );\n"
+" static_assert(std::extent_v<decltype(m_funcs)> == size_t(funcNames.count()));\n"
+" for (int i = 0; i < funcNames.count(); ++i) {\n"
+" m_funcs[i] = inst->getInstanceProcAddr(funcNames.at(i));\n"
" if (i < %d && !m_funcs[i])\n"
-" qWarning(\"QVulkanFunctions: Failed to resolve %%s\", funcNames[i]);\n"
+" qWarning(\"QVulkanFunctions: Failed to resolve %%s\", funcNames.at(i));\n"
" }\n"
"}\n"
"\n%s"
@@ -532,13 +516,14 @@ bool genVulkanFunctionsPC(const QList<VkSpecParser::Command> &commands,
"{\n"
" QVulkanFunctions *f = inst->functions();\n"
" Q_ASSERT(f);\n\n"
-" static const char *funcNames[] = {\n"
+" static constexpr auto funcNames = qOffsetStringArray(\n"
"%s\n"
-" };\n"
-" for (int i = 0; i < %d; ++i) {\n"
-" m_funcs[i] = f->vkGetDeviceProcAddr(device, funcNames[i]);\n"
+" );\n"
+" static_assert(std::extent_v<decltype(m_funcs)> == size_t(funcNames.count()));\n"
+" for (int i = 0; i < funcNames.count(); ++i) {\n"
+" m_funcs[i] = f->vkGetDeviceProcAddr(device, funcNames.at(i));\n"
" if (i < %d && !m_funcs[i])\n"
-" qWarning(\"QVulkanDeviceFunctions: Failed to resolve %%s\", funcNames[i]);\n"
+" qWarning(\"QVulkanDeviceFunctions: Failed to resolve %%s\", funcNames.at(i));\n"
" }\n"
"}\n"
"\n"
@@ -547,9 +532,7 @@ bool genVulkanFunctionsPC(const QList<VkSpecParser::Command> &commands,
QString devCmdWrapperStr;
QString instCmdWrapperStr;
int devIdx = 0;
- int devCount = 0;
int instIdx = 0;
- int instCount = 0;
QString devCmdNamesStr;
QString instCmdNamesStr;
int vulkan10DevCount = 0;
@@ -575,11 +558,6 @@ bool genVulkanFunctionsPC(const QList<VkSpecParser::Command> &commands,
*dst += QStringLiteral(" \"");
*dst += c.cmd.name;
*dst += QStringLiteral("\",\n");
-
- if (c.deviceLevel)
- devCount += 1;
- else
- instCount += 1;
}
if (version == QStringLiteral("VK_VERSION_1_0")) {
vulkan10InstCount = instIdx;
@@ -589,17 +567,17 @@ bool genVulkanFunctionsPC(const QList<VkSpecParser::Command> &commands,
devCmdWrapperStr += "#endif\n\n";
}
- if (devCmdNamesStr.count() > 2)
- devCmdNamesStr = devCmdNamesStr.left(devCmdNamesStr.count() - 2);
- if (instCmdNamesStr.count() > 2)
- instCmdNamesStr = instCmdNamesStr.left(instCmdNamesStr.count() - 2);
+ if (devCmdNamesStr.size() > 2)
+ devCmdNamesStr.chop(2);
+ if (instCmdNamesStr.size() > 2)
+ instCmdNamesStr.chop(2);
const QString str =
QString::asprintf(s, preamble.get(licHeaderFn).constData(),
instCmdWrapperStr.toUtf8().constData(),
- instCmdNamesStr.toUtf8().constData(), instCount, vulkan10InstCount,
+ instCmdNamesStr.toUtf8().constData(), vulkan10InstCount,
devCmdWrapperStr.toUtf8().constData(),
- devCmdNamesStr.toUtf8().constData(), devCount, vulkan10DevCount);
+ devCmdNamesStr.toUtf8().constData(), vulkan10DevCount);
f.write(str.toUtf8());
@@ -633,7 +611,7 @@ int main(int argc, char **argv)
QStringLiteral("vkGetInstanceProcAddr"),
QStringLiteral("vkEnumerateInstanceVersion")
};
- for (int i = 0; i < commands.count(); ++i) {
+ for (int i = 0; i < commands.size(); ++i) {
if (ignoredFuncs.contains(commands[i].cmd.name))
commands.remove(i--);
}
diff --git a/src/tools/rcc/CMakeLists.txt b/src/tools/rcc/CMakeLists.txt
index efeadf803a..35a72c43fe 100644
--- a/src/tools/rcc/CMakeLists.txt
+++ b/src/tools/rcc/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from rcc.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## rcc Tool:
@@ -6,9 +7,10 @@
qt_get_tool_target_name(target_name rcc)
qt_internal_add_tool(${target_name}
+ TRY_RUN
TARGET_DESCRIPTION "Qt Resource Compiler"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
main.cpp
rcc.cpp rcc.h
@@ -16,26 +18,16 @@ qt_internal_add_tool(${target_name}
QT_NO_CAST_FROM_ASCII
QT_NO_FOREACH
QT_RCC
+ QT_USE_NODISCARD_FILE_OPEN
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
)
qt_internal_return_unless_building_tools()
-#### Keys ignored in scope 1:.:.:rcc.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt Resource Compiler"
-# _OPTION = "host_build"
-
## Scopes:
#####################################################################
-qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_zstd AND NOT CMAKE_CROSSCOMPILING
- DEFINES
- QT_FEATURE_zstd=1
+qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_zstd
LIBRARIES
- ZSTD::ZSTD
-)
-
-qt_internal_extend_target(${target_name} CONDITION CMAKE_CROSSCOMPILING OR NOT QT_FEATURE_zstd
- DEFINES
- QT_FEATURE_zstd=-1
+ WrapZSTD::WrapZSTD
)
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index d9d211c19d..03709ccbd4 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** 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) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <rcc.h>
@@ -49,6 +24,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
void dumpRecursive(const QDir &dir, QTextStream &out)
{
const QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
@@ -57,9 +34,9 @@ void dumpRecursive(const QDir &dir, QTextStream &out)
if (entry.isDir()) {
dumpRecursive(entry.filePath(), out);
} else {
- out << QLatin1String("<file>")
+ out << "<file>"_L1
<< entry.filePath()
- << QLatin1String("</file>\n");
+ << "</file>\n"_L1;
}
}
}
@@ -69,7 +46,7 @@ int createProject(const QString &outFileName)
QDir currentDir = QDir::current();
QString currentDirName = currentDir.dirName();
if (currentDirName.isEmpty())
- currentDirName = QLatin1String("root");
+ currentDirName = "root"_L1;
QFile file;
bool isOk = false;
@@ -87,14 +64,14 @@ int createProject(const QString &outFileName)
}
QTextStream out(&file);
- out << QLatin1String("<!DOCTYPE RCC><RCC version=\"1.0\">\n"
- "<qresource>\n");
+ out << "<!DOCTYPE RCC><RCC version=\"1.0\">\n"
+ "<qresource>\n"_L1;
// use "." as dir to get relative file paths
- dumpRecursive(QDir(QLatin1String(".")), out);
+ dumpRecursive(QDir("."_L1), out);
- out << QLatin1String("</qresource>\n"
- "</RCC>\n");
+ out << "</qresource>\n"
+ "</RCC>\n"_L1;
return 0;
}
@@ -105,11 +82,11 @@ QString makefileEscape(const QString &filepath)
// Always use forward slashes
QString result = QDir::cleanPath(filepath);
// Spaces are escaped with a backslash
- result.replace(QLatin1Char(' '), QLatin1String("\\ "));
+ result.replace(u' ', "\\ "_L1);
// Pipes are escaped with a backslash
- result.replace(QLatin1Char('|'), QLatin1String("\\|"));
+ result.replace(u'|', "\\|"_L1);
// Dollars are escaped with a dollar
- result.replace(QLatin1Char('$'), QLatin1String("$$"));
+ result.replace(u'$', "$$"_L1);
return result;
}
@@ -118,16 +95,16 @@ void writeDepFile(QIODevice &iodev, const QStringList &depsList, const QString &
{
QTextStream out(&iodev);
out << qPrintable(makefileEscape(targetName));
- out << QLatin1Char(':');
+ out << QChar(u':');
// Write depfile
for (int i = 0; i < depsList.size(); ++i) {
- out << QLatin1Char(' ');
+ out << QChar(u' ');
out << qPrintable(makefileEscape(depsList.at(i)));
}
- out << QLatin1Char('\n');
+ out << QChar(u'\n');
}
int runRcc(int argc, char *argv[])
@@ -139,7 +116,7 @@ int runRcc(int argc, char *argv[])
// If you use this code as an example for a translated app, make sure to translate the strings.
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- parser.setApplicationDescription(QLatin1String("Qt Resource Compiler version " QT_VERSION_STR));
+ parser.setApplicationDescription("Qt Resource Compiler version " QT_VERSION_STR ""_L1);
parser.addHelpOption();
parser.addVersionOption();
@@ -233,9 +210,9 @@ int runRcc(int argc, char *argv[])
bool ok = false;
formatVersion = parser.value(formatVersionOption).toUInt(&ok);
if (!ok) {
- errorMsg = QLatin1String("Invalid format version specified");
+ errorMsg = "Invalid format version specified"_L1;
} else if (formatVersion < 1 || formatVersion > 3) {
- errorMsg = QLatin1String("Unsupported format version specified");
+ errorMsg = "Unsupported format version specified"_L1;
}
}
@@ -244,19 +221,22 @@ int runRcc(int argc, char *argv[])
library.setInitName(parser.value(nameOption));
if (parser.isSet(rootOption)) {
library.setResourceRoot(QDir::cleanPath(parser.value(rootOption)));
- if (library.resourceRoot().isEmpty()
- || library.resourceRoot().at(0) != QLatin1Char('/'))
- errorMsg = QLatin1String("Root must start with a /");
+ if (library.resourceRoot().isEmpty() || library.resourceRoot().at(0) != u'/')
+ errorMsg = "Root must start with a /"_L1;
}
if (parser.isSet(compressionAlgoOption))
library.setCompressionAlgorithm(RCCResourceLibrary::parseCompressionAlgorithm(parser.value(compressionAlgoOption), &errorMsg));
- if (formatVersion < 3 && library.compressionAlgorithm() == RCCResourceLibrary::CompressionAlgorithm::Zstd)
- errorMsg = QLatin1String("Zstandard compression requires format version 3 or higher");
- if (parser.isSet(nocompressOption))
- library.setCompressionAlgorithm(RCCResourceLibrary::CompressionAlgorithm::None);
if (parser.isSet(noZstdOption))
library.setNoZstd(true);
+ if (library.compressionAlgorithm() == RCCResourceLibrary::CompressionAlgorithm::Zstd) {
+ if (formatVersion < 3)
+ errorMsg = "Zstandard compression requires format version 3 or higher"_L1;
+ if (library.noZstd())
+ errorMsg = "--compression-algo=zstd and --no-zstd both specified."_L1;
+ }
+ if (parser.isSet(nocompressOption))
+ library.setCompressionAlgorithm(RCCResourceLibrary::CompressionAlgorithm::None);
if (parser.isSet(compressOption) && errorMsg.isEmpty()) {
int level = library.parseCompressionLevel(library.compressionAlgorithm(), parser.value(compressOption), &errorMsg);
library.setCompressLevel(level);
@@ -267,25 +247,25 @@ int runRcc(int argc, char *argv[])
library.setFormat(RCCResourceLibrary::Binary);
if (parser.isSet(generatorOption)) {
auto value = parser.value(generatorOption);
- if (value == QLatin1String("cpp")) {
+ if (value == "cpp"_L1) {
library.setFormat(RCCResourceLibrary::C_Code);
- } else if (value == QLatin1String("python")) {
+ } else if (value == "python"_L1) {
library.setFormat(RCCResourceLibrary::Python_Code);
- } else if (value == QLatin1String("python2")) { // ### fixme Qt 7: remove
+ } else if (value == "python2"_L1) { // ### fixme Qt 7: remove
qWarning("Format python2 is no longer supported, defaulting to python.");
library.setFormat(RCCResourceLibrary::Python_Code);
} else {
- errorMsg = QLatin1String("Invalid generator: ") + value;
+ errorMsg = "Invalid generator: "_L1 + value;
}
}
if (parser.isSet(passOption)) {
- if (parser.value(passOption) == QLatin1String("1"))
+ if (parser.value(passOption) == "1"_L1)
library.setFormat(RCCResourceLibrary::Pass1);
- else if (parser.value(passOption) == QLatin1String("2"))
+ else if (parser.value(passOption) == "2"_L1)
library.setFormat(RCCResourceLibrary::Pass2);
else
- errorMsg = QLatin1String("Pass number must be 1 or 2");
+ errorMsg = "Pass number must be 1 or 2"_L1;
}
if (parser.isSet(namespaceOption))
library.setUseNameSpace(!library.useNameSpace());
@@ -298,7 +278,7 @@ int runRcc(int argc, char *argv[])
const QStringList filenamesIn = parser.positionalArguments();
for (const QString &file : filenamesIn) {
- if (file == QLatin1String("-"))
+ if (file == "-"_L1)
continue;
else if (!QFile::exists(file)) {
qWarning("%s: File does not exist '%s'", argv[0], qPrintable(file));
@@ -323,7 +303,8 @@ int runRcc(int argc, char *argv[])
return 1;
}
QFile errorDevice;
- errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text);
+ if (!errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text))
+ return 1;
if (library.verbose())
errorDevice.write("Qt resource compiler\n");
@@ -350,7 +331,7 @@ int runRcc(int argc, char *argv[])
}
- if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
+ if (outFilename.isEmpty() || outFilename == "-"_L1) {
#ifdef Q_OS_WIN
// Make sure fwrite to stdout doesn't do LF->CRLF
if (library.format() == RCCResourceLibrary::Binary)
@@ -361,7 +342,12 @@ int runRcc(int argc, char *argv[])
mode &= ~QIODevice::Text;
#endif // Q_OS_WIN
// using this overload close() only flushes.
- out.open(stdout, mode);
+ if (!out.open(stdout, mode)) {
+ const QString msg = QString::fromLatin1("Unable to open standard output for writing: %1\n")
+ .arg(out.errorString());
+ errorDevice.write(msg.toUtf8());
+ return 1;
+ }
} else {
out.setFileName(outFilename);
if (!out.open(mode)) {
@@ -398,7 +384,7 @@ int runRcc(int argc, char *argv[])
QFile depout;
depout.setFileName(depFilename);
- if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
+ if (outFilename.isEmpty() || outFilename == "-"_L1) {
const QString msg = QString::fromUtf8("Unable to write depfile when outputting to stdout!\n");
errorDevice.write(msg.toUtf8());
return 1;
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 1825c77b53..444e9c4ae5 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** 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) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "rcc.h"
@@ -33,7 +8,7 @@
#include <qdatetime.h>
#include <qdebug.h>
#include <qdir.h>
-#include <qdiriterator.h>
+#include <qdirlisting.h>
#include <qfile.h>
#include <qiodevice.h>
#include <qlocale.h>
@@ -50,6 +25,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
enum {
CONSTANT_USENAMESPACE = 1,
CONSTANT_COMPRESSLEVEL_DEFAULT = -1,
@@ -58,14 +35,6 @@ enum {
CONSTANT_COMPRESSTHRESHOLD_DEFAULT = 70
};
-#if QT_CONFIG(zstd) && QT_VERSION >= QT_VERSION_CHECK(6,0,0)
-# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::Zstd
-#elif !defined(QT_NO_COMPRESS)
-# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::Zlib
-#else
-# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::None
-#endif
-
void RCCResourceLibrary::write(const char *str, int len)
{
int n = m_out.size();
@@ -106,15 +75,18 @@ public:
CompressedZstd = 0x04
};
- RCCFileInfo(const QString &name = QString(), const QFileInfo &fileInfo = QFileInfo(),
- QLocale::Language language = QLocale::C,
- QLocale::Territory territory = QLocale::AnyTerritory,
- uint flags = NoFlags,
- RCCResourceLibrary::CompressionAlgorithm compressAlgo = CONSTANT_COMPRESSALGO_DEFAULT,
- int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT,
- int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT,
- bool noZstd = false);
+
+ RCCFileInfo() = default;
+ RCCFileInfo(const QString &name, const QFileInfo &fileInfo, QLocale::Language language,
+ QLocale::Territory territory, uint flags,
+ RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel,
+ int compressThreshold, bool noZstd, bool isEmpty);
+
~RCCFileInfo();
+ RCCFileInfo(const RCCFileInfo &) = delete;
+ RCCFileInfo &operator=(const RCCFileInfo &) = delete;
+ RCCFileInfo(RCCFileInfo &&) = default;
+ RCCFileInfo &operator=(RCCFileInfo &&other) = delete;
QString resourceName() const;
@@ -123,41 +95,40 @@ public:
qint64 writeDataName(RCCResourceLibrary &, qint64 offset);
void writeDataInfo(RCCResourceLibrary &lib);
- int m_flags;
+ int m_flags = NoFlags;
+ QLocale::Language m_language = QLocale::C;
+ QLocale::Territory m_territory = QLocale::AnyTerritory;
QString m_name;
- QLocale::Language m_language;
- QLocale::Territory m_territory;
QFileInfo m_fileInfo;
- RCCFileInfo *m_parent;
+ RCCFileInfo *m_parent = nullptr;
QMultiHash<QString, RCCFileInfo *> m_children;
- RCCResourceLibrary::CompressionAlgorithm m_compressAlgo;
- int m_compressLevel;
- int m_compressThreshold;
-
- qint64 m_nameOffset;
- qint64 m_dataOffset;
- qint64 m_childOffset;
- bool m_noZstd;
+
+ RCCResourceLibrary::CompressionAlgorithm m_compressAlgo = RCCResourceLibrary::CompressionAlgorithm::Best;
+ int m_compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT;
+ int m_compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT;
+ bool m_noZstd = false;
+ bool m_isEmpty = false;
+
+ qint64 m_nameOffset = 0;
+ qint64 m_dataOffset = 0;
+ qint64 m_childOffset = 0;
};
-RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
- QLocale::Language language, QLocale::Territory territory, uint flags,
- RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel, int compressThreshold,
- bool noZstd)
+RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo, QLocale::Language language,
+ QLocale::Territory territory, uint flags,
+ RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel,
+ int compressThreshold, bool noZstd, bool isEmpty)
+ : m_flags(flags),
+ m_language(language),
+ m_territory(territory),
+ m_name(name),
+ m_fileInfo(fileInfo),
+ m_compressAlgo(compressAlgo),
+ m_compressLevel(compressLevel),
+ m_compressThreshold(compressThreshold),
+ m_noZstd(noZstd),
+ m_isEmpty(isEmpty)
{
- m_name = name;
- m_fileInfo = fileInfo;
- m_language = language;
- m_territory = territory;
- m_flags = flags;
- m_parent = nullptr;
- m_nameOffset = 0;
- m_dataOffset = 0;
- m_childOffset = 0;
- m_compressAlgo = compressAlgo;
- m_compressLevel = compressLevel;
- m_compressThreshold = compressThreshold;
- m_noZstd = noZstd;
}
RCCFileInfo::~RCCFileInfo()
@@ -169,8 +140,9 @@ QString RCCFileInfo::resourceName() const
{
QString resource = m_name;
for (RCCFileInfo *p = m_parent; p; p = p->m_parent)
- resource = resource.prepend(p->m_name + QLatin1Char('/'));
- return QLatin1Char(':') + resource;
+ resource = resource.prepend(p->m_name + u'/');
+ resource.prepend(u':');
+ return resource;
}
void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
@@ -229,7 +201,7 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
if (lib.formatVersion() >= 2) {
// last modified time stamp
- const QDateTime lastModified = m_fileInfo.lastModified();
+ const QDateTime lastModified = m_fileInfo.lastModified(QTimeZone::UTC);
quint64 lastmod = quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0);
static const quint64 sourceDate = 1000 * qgetenv("QT_RCC_SOURCE_DATE_OVERRIDE").toULongLong();
if (sourceDate != 0)
@@ -256,14 +228,18 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
//capture the offset
m_dataOffset = offset;
+ QByteArray data;
- //find the data to be written
- QFile file(m_fileInfo.absoluteFilePath());
- if (!file.open(QFile::ReadOnly)) {
- *errorMessage = msgOpenReadFailed(m_fileInfo.absoluteFilePath(), file.errorString());
- return 0;
+ if (!m_isEmpty) {
+ //find the data to be written
+ QFile file(m_fileInfo.absoluteFilePath());
+ if (!file.open(QFile::ReadOnly)) {
+ *errorMessage = msgOpenReadFailed(m_fileInfo.absoluteFilePath(), file.errorString());
+ return 0;
+ }
+
+ data = file.readAll();
}
- QByteArray data = file.readAll();
// Check if compression is useful for this file
if (data.size() != 0) {
@@ -402,7 +378,7 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
}
// write the length
- lib.writeNumber2(m_name.length());
+ lib.writeNumber2(m_name.size());
if (text || pass1)
lib.writeString("\n ");
else if (python)
@@ -419,14 +395,14 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
// write the m_name
const QChar *unicode = m_name.unicode();
- for (int i = 0; i < m_name.length(); ++i) {
+ for (int i = 0; i < m_name.size(); ++i) {
lib.writeNumber2(unicode[i].unicode());
if ((text || pass1) && i % 16 == 0)
lib.writeString("\n ");
else if (python && i % 16 == 0)
lib.writeString("\\\n");
}
- offset += m_name.length()*2;
+ offset += m_name.size()*2;
// done
if (text || pass1)
@@ -445,14 +421,15 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
///////////////////////////////////////////////////////////
RCCResourceLibrary::Strings::Strings() :
- TAG_RCC(QLatin1String("RCC")),
- TAG_RESOURCE(QLatin1String("qresource")),
- TAG_FILE(QLatin1String("file")),
- ATTRIBUTE_LANG(QLatin1String("lang")),
- ATTRIBUTE_PREFIX(QLatin1String("prefix")),
- ATTRIBUTE_ALIAS(QLatin1String("alias")),
- ATTRIBUTE_THRESHOLD(QLatin1String("threshold")),
- ATTRIBUTE_COMPRESS(QLatin1String("compress")),
+ TAG_RCC("RCC"_L1),
+ TAG_RESOURCE("qresource"_L1),
+ TAG_FILE("file"_L1),
+ ATTRIBUTE_LANG("lang"_L1),
+ ATTRIBUTE_PREFIX("prefix"_L1),
+ ATTRIBUTE_ALIAS("alias"_L1),
+ ATTRIBUTE_EMPTY("empty"_L1),
+ ATTRIBUTE_THRESHOLD("threshold"_L1),
+ ATTRIBUTE_COMPRESS("compress"_L1),
ATTRIBUTE_COMPRESSALGO(QStringLiteral("compression-algorithm"))
{
}
@@ -461,7 +438,7 @@ RCCResourceLibrary::RCCResourceLibrary(quint8 formatVersion)
: m_root(nullptr),
m_format(C_Code),
m_verbose(false),
- m_compressionAlgo(CONSTANT_COMPRESSALGO_DEFAULT),
+ m_compressionAlgo(CompressionAlgorithm::Best),
m_compressLevel(CONSTANT_COMPRESSLEVEL_DEFAULT),
m_compressThreshold(CONSTANT_COMPRESSTHRESHOLD_DEFAULT),
m_treeOffset(0),
@@ -495,11 +472,22 @@ enum RCCXmlTag {
};
Q_DECLARE_TYPEINFO(RCCXmlTag, Q_PRIMITIVE_TYPE);
+static bool parseBoolean(QStringView value, QString *errorMsg)
+{
+ if (value.compare("true"_L1, Qt::CaseInsensitive) == 0)
+ return true;
+ if (value.compare("false"_L1, Qt::CaseInsensitive) == 0)
+ return false;
+
+ *errorMsg = QString::fromLatin1("Invalid value for boolean attribute: '%1'").arg(value);
+ return false;
+}
+
bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
const QString &fname, QString currentPath, bool listMode)
{
Q_ASSERT(m_errorDevice);
- const QChar slash = QLatin1Char('/');
+ const QChar slash = u'/';
if (!currentPath.isEmpty() && !currentPath.endsWith(slash))
currentPath += slash;
@@ -510,6 +498,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
QLocale::Language language = QLocale::c().language();
QLocale::Territory territory = QLocale::c().territory();
QString alias;
+ bool empty = false;
auto compressAlgo = m_compressionAlgo;
int compressLevel = m_compressLevel;
int compressThreshold = m_compressThreshold;
@@ -520,12 +509,12 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
case QXmlStreamReader::StartElement:
if (reader.name() == m_strings.TAG_RCC) {
if (!tokens.isEmpty())
- reader.raiseError(QLatin1String("expected <RCC> tag"));
+ reader.raiseError("expected <RCC> tag"_L1);
else
tokens.push(RccTag);
} else if (reader.name() == m_strings.TAG_RESOURCE) {
if (tokens.isEmpty() || tokens.top() != RccTag) {
- reader.raiseError(QLatin1String("unexpected <RESOURCE> tag"));
+ reader.raiseError("unexpected <RESOURCE> tag"_L1);
} else {
tokens.push(ResourceTag);
@@ -537,7 +526,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
QString attribute = attributes.value(m_strings.ATTRIBUTE_LANG).toString();
QLocale lang = QLocale(attribute);
language = lang.language();
- if (2 == attribute.length()) {
+ if (2 == attribute.size()) {
// Language only
territory = QLocale::AnyTerritory;
} else {
@@ -555,7 +544,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
}
} else if (reader.name() == m_strings.TAG_FILE) {
if (tokens.isEmpty() || tokens.top() != ResourceTag) {
- reader.raiseError(QLatin1String("unexpected <FILE> tag"));
+ reader.raiseError("unexpected <FILE> tag"_L1);
} else {
tokens.push(FileTag);
@@ -569,6 +558,11 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
compressThreshold = m_compressThreshold;
QString errorString;
+ if (attributes.hasAttribute(m_strings.ATTRIBUTE_EMPTY))
+ empty = parseBoolean(attributes.value(m_strings.ATTRIBUTE_EMPTY), &errorString);
+ else
+ empty = false;
+
if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESSALGO))
compressAlgo = parseCompressionAlgorithm(attributes.value(m_strings.ATTRIBUTE_COMPRESSALGO), &errorString);
if (errorString.isEmpty() && attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) {
@@ -587,7 +581,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
reader.raiseError(errorString);
}
} else {
- reader.raiseError(QString(QLatin1String("unexpected tag: %1")).arg(reader.name().toString()));
+ reader.raiseError("unexpected tag: %1"_L1.arg(reader.name().toString()));
}
break;
@@ -596,17 +590,17 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (!tokens.isEmpty() && tokens.top() == RccTag)
tokens.pop();
else
- reader.raiseError(QLatin1String("unexpected closing tag"));
+ reader.raiseError("unexpected closing tag"_L1);
} else if (reader.name() == m_strings.TAG_RESOURCE) {
if (!tokens.isEmpty() && tokens.top() == ResourceTag)
tokens.pop();
else
- reader.raiseError(QLatin1String("unexpected closing tag"));
+ reader.raiseError("unexpected closing tag"_L1);
} else if (reader.name() == m_strings.TAG_FILE) {
if (!tokens.isEmpty() && tokens.top() == FileTag)
tokens.pop();
else
- reader.raiseError(QLatin1String("unexpected closing tag"));
+ reader.raiseError("unexpected closing tag"_L1);
}
break;
@@ -614,7 +608,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (reader.isWhitespace())
break;
if (tokens.isEmpty() || tokens.top() != FileTag) {
- reader.raiseError(QLatin1String("unexpected text"));
+ reader.raiseError("unexpected text"_L1);
} else {
QString fileName = reader.text().toString();
if (fileName.isEmpty()) {
@@ -626,7 +620,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
alias = fileName;
alias = QDir::cleanPath(alias);
- while (alias.startsWith(QLatin1String("../")))
+ while (alias.startsWith("../"_L1))
alias.remove(0, 3);
alias = QDir::cleanPath(m_resourceRoot) + prefix + alias;
@@ -640,13 +634,12 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
alias += slash;
QStringList filePaths;
- QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories);
- while (it.hasNext()) {
- it.next();
- if (it.fileName() == QLatin1String(".")
- || it.fileName() == QLatin1String(".."))
+ using F = QDirListing::IteratorFlag;
+ for (const auto &entry : QDirListing(dir, F::FollowSymlinks | F::Recursive)) {
+ const QString &fileName = entry.fileName();
+ if (fileName == "."_L1 || fileName == ".."_L1)
continue;
- filePaths.append(it.filePath());
+ filePaths.emplace_back(entry.filePath());
}
// make rcc output deterministic
@@ -660,7 +653,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
child.isDir() ? RCCFileInfo::Directory
: RCCFileInfo::NoFlags,
compressAlgo, compressLevel, compressThreshold,
- m_noZstd));
+ m_noZstd, empty));
if (!arc)
m_failedResources.push_back(child.fileName());
}
@@ -675,7 +668,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
compressAlgo,
compressLevel,
compressThreshold,
- m_noZstd)
+ m_noZstd, empty)
);
if (!arc)
m_failedResources.push_back(absFileName);
@@ -714,15 +707,15 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
m_errorDevice->write(msg.toUtf8());
if (!listMode && m_format == Binary) {
// create dummy entry, otherwise loading with QResource will crash
- m_root = new RCCFileInfo(QString(), QFileInfo(),
- QLocale::C, QLocale::AnyTerritory, RCCFileInfo::Directory);
+ m_root = new RCCFileInfo{};
+ m_root->m_flags = RCCFileInfo::Directory;
}
}
return true;
}
-bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
+bool RCCResourceLibrary::addFile(const QString &alias, RCCFileInfo file)
{
Q_ASSERT(m_errorDevice);
if (file.m_fileInfo.size() > 0xffffffff) {
@@ -730,17 +723,21 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
m_errorDevice->write(msg.toUtf8());
return false;
}
- if (!m_root)
- m_root = new RCCFileInfo(QString(), QFileInfo(), QLocale::C, QLocale::AnyTerritory, RCCFileInfo::Directory);
+ if (!m_root) {
+ m_root = new RCCFileInfo{};
+ m_root->m_flags = RCCFileInfo::Directory;
+ }
RCCFileInfo *parent = m_root;
- const QStringList nodes = alias.split(QLatin1Char('/'));
+ const QStringList nodes = alias.split(u'/');
for (int i = 1; i < nodes.size()-1; ++i) {
const QString node = nodes.at(i);
if (node.isEmpty())
continue;
if (!parent->m_children.contains(node)) {
- RCCFileInfo *s = new RCCFileInfo(node, QFileInfo(), QLocale::C, QLocale::AnyTerritory, RCCFileInfo::Directory);
+ RCCFileInfo *s = new RCCFileInfo{};
+ s->m_name = node;
+ s->m_flags = RCCFileInfo::Directory;
s->m_parent = parent;
parent->m_children.insert(node, s);
parent = s;
@@ -750,14 +747,14 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
}
const QString filename = nodes.at(nodes.size()-1);
- RCCFileInfo *s = new RCCFileInfo(file);
+ RCCFileInfo *s = new RCCFileInfo(std::move(file));
s->m_parent = parent;
auto cbegin = parent->m_children.constFind(filename);
auto cend = parent->m_children.constEnd();
for (auto it = cbegin; it != cend; ++it) {
if (it.key() == filename && it.value()->m_language == s->m_language &&
it.value()->m_territory == s->m_territory) {
- for (const QString &name : qAsConst(m_fileNames)) {
+ for (const QString &name : std::as_const(m_fileNames)) {
qWarning("%s: Warning: potential duplicate alias detected: '%s'",
qPrintable(name), qPrintable(filename));
}
@@ -793,8 +790,8 @@ bool RCCResourceLibrary::readFiles(bool listMode, QIODevice &errorDevice)
QFile fileIn;
QString fname = m_fileNames.at(i);
QString pwd;
- if (fname == QLatin1String("-")) {
- fname = QLatin1String("(stdin)");
+ if (fname == "-"_L1) {
+ fname = "(stdin)"_L1;
pwd = QDir::currentPath();
fileIn.setFileName(fname);
if (!fileIn.open(stdin, QIODevice::ReadOnly)) {
@@ -845,7 +842,7 @@ QStringList RCCResourceLibrary::dataFiles() const
// Determine map of resource identifier (':/newPrefix/images/p1.png') to file via recursion
static void resourceDataFileMapRecursion(const RCCFileInfo *m_root, const QString &path, RCCResourceLibrary::ResourceDataFileMap &m)
{
- const QChar slash = QLatin1Char('/');
+ const QChar slash = u'/';
const auto cend = m_root->m_children.constEnd();
for (auto it = m_root->m_children.constBegin(); it != cend; ++it) {
const RCCFileInfo *child = it.value();
@@ -862,27 +859,27 @@ RCCResourceLibrary::ResourceDataFileMap RCCResourceLibrary::resourceDataFileMap(
{
ResourceDataFileMap rc;
if (m_root)
- resourceDataFileMapRecursion(m_root, QString(QLatin1Char(':')), rc);
+ resourceDataFileMapRecursion(m_root, QString(u':'), rc);
return rc;
}
RCCResourceLibrary::CompressionAlgorithm RCCResourceLibrary::parseCompressionAlgorithm(QStringView value, QString *errorMsg)
{
- if (value == QLatin1String("best"))
+ if (value == "best"_L1)
return CompressionAlgorithm::Best;
- if (value == QLatin1String("zlib")) {
+ if (value == "zlib"_L1) {
#ifdef QT_NO_COMPRESS
- *errorMsg = QLatin1String("zlib support not compiled in");
+ *errorMsg = "zlib support not compiled in"_L1;
#else
return CompressionAlgorithm::Zlib;
#endif
- } else if (value == QLatin1String("zstd")) {
+ } else if (value == "zstd"_L1) {
#if QT_CONFIG(zstd)
return CompressionAlgorithm::Zstd;
#else
- *errorMsg = QLatin1String("Zstandard support not compiled in");
+ *errorMsg = "Zstandard support not compiled in"_L1;
#endif
- } else if (value != QLatin1String("none")) {
+ } else if (value != "none"_L1) {
*errorMsg = QString::fromLatin1("Unknown compression algorithm '%1'").arg(value);
}
@@ -932,13 +929,17 @@ bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &tempDevice, QIO
m_errorDevice->write("No data signature found\n");
return false;
}
+
+ if (c != pattern[i]) {
+ for (int k = 0; k < i; ++k)
+ outDevice.putChar(pattern[k]);
+ i = 0;
+ }
+
if (c == pattern[i]) {
++i;
} else {
- for (int k = 0; k < i; ++k)
- outDevice.putChar(pattern[k]);
outDevice.putChar(c);
- i = 0;
}
}
@@ -1097,6 +1098,10 @@ bool RCCResourceLibrary::writeHeader()
writeString("\n**\n");
writeString("** WARNING! All changes made in this file will be lost!\n");
writeString( "*****************************************************************************/\n\n");
+ writeString("#ifdef _MSC_VER\n"
+ "// disable informational message \"function ... selected for automatic inline expansion\"\n"
+ "#pragma warning (disable: 4711)\n"
+ "#endif\n\n");
break;
case Python_Code:
writeString("# Resource object code (Python 3)\n");
@@ -1348,7 +1353,7 @@ bool RCCResourceLibrary::writeInitializer()
//write("\nQT_BEGIN_NAMESPACE\n");
QString initNameStr = m_initName;
if (!initNameStr.isEmpty()) {
- initNameStr.prepend(QLatin1Char('_'));
+ initNameStr.prepend(u'_');
auto isAsciiLetterOrNumber = [] (QChar c) -> bool {
ushort ch = c.unicode();
return (ch >= '0' && ch <= '9') ||
@@ -1358,7 +1363,7 @@ bool RCCResourceLibrary::writeInitializer()
};
for (QChar &c : initNameStr) {
if (!isAsciiLetterOrNumber(c))
- c = QLatin1Char('_');
+ c = u'_';
}
}
QByteArray initName = initNameStr.toLatin1();
@@ -1377,7 +1382,9 @@ bool RCCResourceLibrary::writeInitializer()
"# define QT_RCC_MANGLE_NAMESPACE(name) name\n"
"#endif\n\n");
- writeString("#ifdef QT_NAMESPACE\n"
+ writeString("#if defined(QT_INLINE_NAMESPACE)\n"
+ "inline namespace QT_NAMESPACE {\n"
+ "#elif defined(QT_NAMESPACE)\n"
"namespace QT_NAMESPACE {\n"
"#endif\n\n");
}
@@ -1478,6 +1485,11 @@ bool RCCResourceLibrary::writeInitializer()
writeString(" return 1;\n");
writeString("}\n\n");
+ // -Wexit-time-destructors was added to clang 3.0.0 in 2011.
+ writeString("#ifdef __clang__\n"
+ "# pragma clang diagnostic push\n"
+ "# pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n"
+ "#endif\n\n");
writeString("namespace {\n"
" struct initializer {\n");
@@ -1490,7 +1502,12 @@ bool RCCResourceLibrary::writeInitializer()
" ~initializer() { " + cleanResources + "(); }\n");
}
writeString(" } dummy;\n"
- "}\n");
+ "}\n\n");
+
+ writeString("#ifdef __clang__\n"
+ "# pragma clang diagnostic pop\n"
+ "#endif\n");
+
} else if (m_format == Binary) {
int i = 4;
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index b6fcb21f5f..60af1c67cf 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** 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) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// Note: A copy of this file is used in Qt Designer (qttools/src/designer/src/lib/shared/rcc_p.h)
@@ -121,13 +96,14 @@ private:
const QString ATTRIBUTE_LANG;
const QString ATTRIBUTE_PREFIX;
const QString ATTRIBUTE_ALIAS;
+ const QString ATTRIBUTE_EMPTY;
const QString ATTRIBUTE_THRESHOLD;
const QString ATTRIBUTE_COMPRESS;
const QString ATTRIBUTE_COMPRESSALGO;
};
friend class RCCFileInfo;
void reset();
- bool addFile(const QString &alias, const RCCFileInfo &file);
+ bool addFile(const QString &alias, RCCFileInfo file);
bool interpretResourceFile(QIODevice *inputDevice, const QString &file,
QString currentPath = QString(), bool listMode = false);
bool writeHeader();
diff --git a/src/tools/shared/depfile_shared.h b/src/tools/shared/depfile_shared.h
index 9fb9bbb863..411a7a1110 100644
--- a/src/tools/shared/depfile_shared.h
+++ b/src/tools/shared/depfile_shared.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QTBASE_DEPFILE_SHARED_H
#define QTBASE_DEPFILE_SHARED_H
diff --git a/src/tools/shared/shellquote_shared.h b/src/tools/shared/shellquote_shared.h
new file mode 100644
index 0000000000..7a9ab691da
--- /dev/null
+++ b/src/tools/shared/shellquote_shared.h
@@ -0,0 +1,82 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef SHELLQUOTE_SHARED_H
+#define SHELLQUOTE_SHARED_H
+
+#include <QDir>
+#include <QRegularExpression>
+#include <QString>
+
+// Copy-pasted from qmake/library/ioutil.cpp
+inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
+{
+ for (int x = arg.size() - 1; x >= 0; --x) {
+ ushort c = arg.unicode()[x].unicode();
+ if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
+ return true;
+ }
+ return false;
+}
+
+static QString shellQuoteUnix(const QString &arg)
+{
+ // Chars that should be quoted (TM). This includes:
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
+ }; // 0-32 \'"$`<>|;&(){}*?#!~[]
+
+ if (!arg.size())
+ return QLatin1String("\"\"");
+
+ QString ret(arg);
+ if (hasSpecialChars(ret, iqm)) {
+ ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
+ ret.prepend(QLatin1Char('\''));
+ ret.append(QLatin1Char('\''));
+ }
+ return ret;
+}
+
+static QString shellQuoteWin(const QString &arg)
+{
+ // Chars that should be quoted (TM). This includes:
+ // - control chars & space
+ // - the shell meta chars "&()<>^|
+ // - the potential separators ,;=
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
+ };
+
+ if (!arg.size())
+ return QLatin1String("\"\"");
+
+ QString ret(arg);
+ if (hasSpecialChars(ret, iqm)) {
+ // Quotes are escaped and their preceding backslashes are doubled.
+ // It's impossible to escape anything inside a quoted string on cmd
+ // level, so the outer quoting must be "suspended".
+ ret.replace(QRegularExpression(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ int i = ret.size();
+ while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
+ --i;
+ ret.insert(i, QLatin1Char('"'));
+ ret.prepend(QLatin1Char('"'));
+ }
+ return ret;
+}
+
+static QString shellQuote(const QString &arg)
+{
+ if (QDir::separator() == QLatin1Char('\\'))
+ return shellQuoteWin(arg);
+ else
+ return shellQuoteUnix(arg);
+}
+
+#endif // SHELLQUOTE_SHARED_H
diff --git a/src/tools/syncqt/CMakeLists.txt b/src/tools/syncqt/CMakeLists.txt
new file mode 100644
index 0000000000..b3ab091aa4
--- /dev/null
+++ b/src/tools/syncqt/CMakeLists.txt
@@ -0,0 +1,80 @@
+if(NOT QT_INTERNAL_AVOID_OVERRIDING_SYNCQT_CONFIG)
+ qt_internal_get_configs_for_flag_manipulation(configs)
+ qt_internal_remove_known_optimization_flags(LANGUAGES CXX CONFIGS ${configs})
+ # The /RTC1 flag is present in the default DEBUG flags list and contradicts -O2 but is not
+ # removed by qt_internal_remove_known_optimization_flags
+ qt_internal_remove_compiler_flags("/RTC1" LANGUAGES CXX CONFIGS ${configs})
+ qt_internal_get_optimize_full_flags(optimize_full_flags)
+ qt_internal_add_compiler_flags(LANGUAGES CXX CONFIGS ${configs} FLAGS "${optimize_full_flags}")
+
+ if(MSVC)
+ qt_internal_add_compiler_flags(LANGUAGES CXX CONFIGS ${configs} FLAGS "/EHsc")
+ else()
+ qt_internal_add_compiler_flags(LANGUAGES CXX CONFIGS ${configs} FLAGS "-fexceptions")
+ endif()
+
+ # Replace all linker flags with those we use in the RelWithDebInfo configuration
+ list(REMOVE_ITEM configs RELWITHDEBINFO)
+ foreach(config IN LISTS configs)
+ set(CMAKE_EXE_LINKER_FLAGS_${config} "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
+ endforeach()
+ qt_internal_skip_sanitizer()
+endif()
+
+set(compile_definitions
+ QT_VERSION_STR="${PROJECT_VERSION}"
+ QT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
+ QT_VERSION_MINOR=${PROJECT_VERSION_MINOR}
+ QT_VERSION_PATCH=${PROJECT_VERSION_PATCH}
+ QT_NAMESPACE="${QT_NAMESPACE}"
+)
+
+qt_get_tool_target_name(target_name syncqt)
+if(NOT QT_SYNC_HEADERS_AT_CONFIGURE_TIME)
+ qt_internal_add_tool(${target_name}
+ DEFINES ${compile_definitions}
+ EXCEPTIONS
+ TOOLS_TARGET Core
+ CORE_LIBRARY None
+ INSTALL_DIR "${INSTALL_LIBEXECDIR}"
+ SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
+ )
+else()
+ set(config_type "")
+ if(NOT QT_INTERNAL_AVOID_OVERRIDING_SYNCQT_CONFIG)
+ set(config_type CONFIG RelWithDebInfo)
+ endif()
+
+ if(CMAKE_OSX_ARCHITECTURES)
+ set(osx_architectures "-DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}")
+ endif()
+
+ if(CMAKE_OSX_SYSROOT)
+ set(osx_sysroot "-DCMAKE_OSX_SYSROOT:STRING=${CMAKE_OSX_SYSROOT}")
+ endif()
+ # Note: configure-time tools reserve the original tool name for the imported executable.
+ # To re-build syncqt use 'syncqt_build' target.
+ qt_internal_add_configure_time_tool(${target_name}
+ DEFINES ${compile_definitions}
+ TOOLS_TARGET Core
+ INSTALL_DIRECTORY "${INSTALL_LIBEXECDIR}"
+ CMAKE_FLAGS
+ -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=TRUE
+ -DCMAKE_CXX_STANDARD:STRING=17
+ # std::filesystem API is only available in macOS 10.15+
+ -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.15
+ "${osx_architectures}"
+ "${osx_sysroot}"
+ SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
+ ${config_type}
+ )
+endif()
+
+# Needs to be called at the end after all relevant target have created
+# when using qt_internal_add_tool.
+# Doesn't work if QT_SYNC_HEADERS_AT_CONFIGURE_TIME is TRUE.
+if(NOT QT_INTERNAL_AVOID_OVERRIDING_SYNCQT_CONFIG)
+ qt_internal_skip_linking_sanitizer()
+endif()
diff --git a/src/tools/syncqt/main.cpp b/src/tools/syncqt/main.cpp
new file mode 100644
index 0000000000..5df7b03fd5
--- /dev/null
+++ b/src/tools/syncqt/main.cpp
@@ -0,0 +1,1844 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+/*
+ * The tool generates deployment artifacts for the Qt builds such as:
+ * - CaMeL case header files named by public C++ symbols located in public module header files
+ * - Header file that contains the module version information, and named as <module>Vesion
+ * - LD version script if applicable
+ * - Aliases or copies of the header files sorted by the generic Qt-types: public/private/qpa
+ * and stored in the corresponding directories.
+ * Also the tool executes conformity checks on each header file if applicable, to make sure they
+ * follow rules that are relevant for their header type.
+ * The tool can be run in two modes: with either '-all' or '-headers' options specified. Depending
+ * on the selected mode, the tool either scans the filesystem to find header files or use the
+ * pre-defined list of header files.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <string_view>
+#include <cstring>
+#include <sstream>
+#include <filesystem>
+#include <unordered_map>
+#include <vector>
+#include <regex>
+#include <map>
+#include <set>
+#include <stdexcept>
+#include <array>
+
+enum ErrorCodes {
+ NoError = 0,
+ InvalidArguments,
+ SyncFailed,
+};
+
+// Enum contains the list of checks that can be executed on header files.
+enum HeaderChecks {
+ NoChecks = 0,
+ NamespaceChecks = 1, /* Checks if header file is wrapped with QT_<BEGIN|END>_NAMESPACE macros */
+ PrivateHeaderChecks = 2, /* Checks if the public header includes a private header */
+ IncludeChecks = 4, /* Checks if the real header file but not an alias is included */
+ WeMeantItChecks = 8, /* Checks if private header files contains 'We meant it' disclaimer */
+ PragmaOnceChecks = 16,
+ /* Checks that lead to the fatal error of the sync process: */
+ CriticalChecks = PrivateHeaderChecks | PragmaOnceChecks,
+ AllChecks = NamespaceChecks | CriticalChecks | IncludeChecks | WeMeantItChecks,
+};
+
+constexpr int LinkerScriptCommentAlignment = 55;
+
+static const std::regex GlobalHeaderRegex("^q(.*)global\\.h$");
+
+constexpr std::string_view ErrorMessagePreamble = "ERROR: ";
+constexpr std::string_view WarningMessagePreamble = "WARNING: ";
+
+// This comparator is used to sort include records in master header.
+// It's used to put q.*global.h file to the top of the list and sort all other files alphabetically.
+bool MasterHeaderIncludeComparator(const std::string &a, const std::string &b)
+{
+ std::smatch amatch;
+ std::smatch bmatch;
+
+ if (std::regex_match(a, amatch, GlobalHeaderRegex)) {
+ if (std::regex_match(b, bmatch, GlobalHeaderRegex)) {
+ return amatch[1].str().empty()
+ || (!bmatch[1].str().empty() && amatch[1].str() < bmatch[1].str());
+ }
+ return true;
+ } else if (std::regex_match(b, bmatch, GlobalHeaderRegex)) {
+ return false;
+ }
+
+ return a < b;
+};
+
+namespace utils {
+std::string asciiToLower(std::string s)
+{
+ std::transform(s.begin(), s.end(), s.begin(),
+ [](unsigned char c) { return (c >= 'A' && c <= 'Z') ? c | 0x20 : c; });
+ return s;
+}
+
+std::string asciiToUpper(std::string s)
+{
+ std::transform(s.begin(), s.end(), s.begin(),
+ [](unsigned char c) { return (c >= 'a' && c <= 'z') ? c & 0xdf : c; });
+ return s;
+}
+
+bool parseVersion(const std::string &version, int &major, int &minor)
+{
+ const size_t separatorPos = version.find('.');
+ if (separatorPos == std::string::npos || separatorPos == (version.size() - 1)
+ || separatorPos == 0)
+ return false;
+
+ try {
+ size_t pos = 0;
+ major = std::stoi(version.substr(0, separatorPos), &pos);
+ if (pos != separatorPos)
+ return false;
+
+ const size_t nextPart = separatorPos + 1;
+ pos = 0;
+ minor = std::stoi(version.substr(nextPart), &pos);
+ if (pos != (version.size() - nextPart))
+ return false;
+ } catch (const std::invalid_argument &) {
+ return false;
+ } catch (const std::out_of_range &) {
+ return false;
+ }
+
+ return true;
+}
+
+class DummyOutputStream : public std::ostream
+{
+ struct : public std::streambuf
+ {
+ int overflow(int c) override { return c; }
+ } buff;
+
+public:
+ DummyOutputStream() : std::ostream(&buff) { }
+} DummyOutput;
+
+void printInternalError()
+{
+ std::cerr << "Internal error. Please create bugreport at https://bugreports.qt.io "
+ "using 'Build tools: Other component.'"
+ << std::endl;
+}
+
+void printFilesystemError(const std::filesystem::filesystem_error &fserr, std::string_view errorMsg)
+{
+ std::cerr << errorMsg << ": " << fserr.path1() << ".\n"
+ << fserr.what() << "(" << fserr.code().value() << ")" << std::endl;
+}
+
+std::filesystem::path normilizedPath(const std::string &path)
+{
+ try {
+ auto result = std::filesystem::path(std::filesystem::weakly_canonical(path).generic_string());
+ return result;
+ } catch (const std::filesystem::filesystem_error &fserr) {
+ printFilesystemError(fserr, "Unable to normalize path");
+ throw;
+ }
+}
+
+bool createDirectories(const std::string &path, std::string_view errorMsg, bool *exists = nullptr)
+{
+ bool result = true;
+ try {
+ if (!std::filesystem::exists(path)) {
+ if (exists)
+ *exists = false;
+ std::filesystem::create_directories(path);
+ } else {
+ if (exists)
+ *exists = true;
+ }
+ } catch (const std::filesystem::filesystem_error &fserr) {
+ result = false;
+ std::cerr << errorMsg << ": " << path << ".\n"
+ << fserr.code().message() << "(" << fserr.code().value() << "):" << fserr.what()
+ << std::endl;
+ }
+ return result;
+}
+
+} // namespace utils
+
+using FileStamp = std::filesystem::file_time_type;
+
+class CommandLineOptions
+{
+ template<typename T>
+ struct CommandLineOption
+ {
+ CommandLineOption(T *_value, bool _isOptional = false)
+ : value(_value), isOptional(_isOptional)
+ {
+ }
+
+ T *value;
+ bool isOptional;
+ };
+
+public:
+ CommandLineOptions(int argc, char *argv[]) : m_isValid(parseArguments(argc, argv)) { }
+
+ bool isValid() const { return m_isValid; }
+
+ const std::string &moduleName() const { return m_moduleName; }
+
+ const std::string &sourceDir() const { return m_sourceDir; }
+
+ const std::string &binaryDir() const { return m_binaryDir; }
+
+ const std::string &includeDir() const { return m_includeDir; }
+
+ const std::string &privateIncludeDir() const { return m_privateIncludeDir; }
+
+ const std::string &qpaIncludeDir() const { return m_qpaIncludeDir; }
+
+ const std::string &rhiIncludeDir() const { return m_rhiIncludeDir; }
+
+ const std::string &ssgIncludeDir() const { return m_ssgIncludeDir; }
+
+ const std::string &stagingDir() const { return m_stagingDir; }
+
+ const std::string &versionScriptFile() const { return m_versionScriptFile; }
+
+ const std::set<std::string> &knownModules() const { return m_knownModules; }
+
+ const std::regex &qpaHeadersRegex() const { return m_qpaHeadersRegex; }
+
+ const std::regex &rhiHeadersRegex() const { return m_rhiHeadersRegex; }
+
+ const std::regex &ssgHeadersRegex() const { return m_ssgHeadersRegex; }
+
+ const std::regex &privateHeadersRegex() const { return m_privateHeadersRegex; }
+
+ const std::regex &publicNamespaceRegex() const { return m_publicNamespaceRegex; }
+
+ const std::set<std::string> &headers() const { return m_headers; }
+
+ const std::set<std::string> &generatedHeaders() const { return m_generatedHeaders; }
+
+ bool scanAllMode() const { return m_scanAllMode; }
+
+ bool isInternal() const { return m_isInternal; }
+
+ bool isNonQtModule() const { return m_isNonQtModule; }
+
+ bool printHelpOnly() const { return m_printHelpOnly; }
+
+ bool debug() const { return m_debug; }
+
+ bool copy() const { return m_copy; }
+
+ bool minimal() const { return m_minimal; }
+
+ bool showOnly() const { return m_showOnly; }
+
+ bool warningsAreErrors() const { return m_warningsAreErrors; }
+
+ void printHelp() const
+ {
+ std::cout << "Usage: syncqt -sourceDir <dir> -binaryDir <dir> -module <module name>"
+ " -includeDir <dir> -privateIncludeDir <dir> -qpaIncludeDir <dir> -rhiIncludeDir <dir> -ssgIncludeDir <dir>"
+ " -stagingDir <dir> <-headers <header list>|-all> [-debug]"
+ " [-versionScript <path>] [-qpaHeadersFilter <regex>] [-rhiHeadersFilter <regex>]"
+ " [-knownModules <module1> <module2>... <moduleN>]"
+ " [-nonQt] [-internal] [-copy]\n"
+ ""
+ "Mandatory arguments:\n"
+ " -module Module name.\n"
+ " -headers List of header files.\n"
+ " -all In 'all' mode syncqt scans source\n"
+ " directory for public qt headers and\n"
+ " artifacts not considering CMake source\n"
+ " tree. The main use cases are the \n"
+ " generating of documentation and creating\n"
+ " API review changes.\n"
+ " -sourceDir Module source directory.\n"
+ " -binaryDir Module build directory.\n"
+ " -includeDir Module include directory where the\n"
+ " generated header files will be located.\n"
+ " -privateIncludeDir Module include directory for the\n"
+ " generated private header files.\n"
+ " -qpaIncludeDir Module include directory for the \n"
+ " generated QPA header files.\n"
+ " -rhiIncludeDir Module include directory for the \n"
+ " generated RHI header files.\n"
+ " -ssgIncludeDir Module include directory for the \n"
+ " generated SSG header files.\n"
+ " -stagingDir Temporary staging directory to collect\n"
+ " artifacts that need to be installed.\n"
+ " -knownModules list of known modules. syncqt uses the\n"
+ " list to check the #include macros\n"
+ " consistency.\n"
+ "Optional arguments:\n"
+ " -internal Indicates that the module is internal.\n"
+ " -nonQt Indicates that the module is not a Qt\n"
+ " module.\n"
+ " -privateHeadersFilter Regex that filters private header files\n"
+ " from the list of 'headers'.\n"
+ " -qpaHeadersFilter Regex that filters qpa header files from.\n"
+ " the list of 'headers'.\n"
+ " -rhiHeadersFilter Regex that filters rhi header files from.\n"
+ " the list of 'headers'.\n"
+ " -ssgHeadersFilter Regex that filters ssg files from.\n"
+ " the list of 'headers'.\n"
+ " -publicNamespaceFilter Symbols that are in the specified\n"
+ " namespace.\n"
+ " are treated as public symbols.\n"
+ " -versionScript Generate linker version script by\n"
+ " provided path.\n"
+ " -debug Enable debug output.\n"
+ " -copy Copy header files instead of creating\n"
+ " aliases.\n"
+ " -minimal Do not create CaMeL case headers for the\n"
+ " public C++ symbols.\n"
+ " -showonly Show actions, but not perform them.\n"
+ " -warningsAreErrors Treat all warnings as errors.\n"
+ " -help Print this help.\n";
+ }
+
+private:
+ template<typename T>
+ [[nodiscard]] bool checkRequiredArguments(const std::unordered_map<std::string, T> &arguments)
+ {
+ bool ret = true;
+ for (const auto &argument : arguments) {
+ if (!argument.second.isOptional
+ && (!argument.second.value || argument.second.value->size()) == 0) {
+ std::cerr << "Missing argument: " << argument.first << std::endl;
+ ret = false;
+ }
+ }
+ return ret;
+ }
+
+ [[nodiscard]] bool parseArguments(int argc, char *argv[])
+ {
+ std::string qpaHeadersFilter;
+ std::string rhiHeadersFilter;
+ std::string ssgHeadersFilter;
+ std::string privateHeadersFilter;
+ std::string publicNamespaceFilter;
+ static std::unordered_map<std::string, CommandLineOption<std::string>> stringArgumentMap = {
+ { "-module", { &m_moduleName } },
+ { "-sourceDir", { &m_sourceDir } },
+ { "-binaryDir", { &m_binaryDir } },
+ { "-privateHeadersFilter", { &privateHeadersFilter, true } },
+ { "-qpaHeadersFilter", { &qpaHeadersFilter, true } },
+ { "-rhiHeadersFilter", { &rhiHeadersFilter, true } },
+ { "-ssgHeadersFilter", { &ssgHeadersFilter, true } },
+ { "-includeDir", { &m_includeDir } },
+ { "-privateIncludeDir", { &m_privateIncludeDir } },
+ { "-qpaIncludeDir", { &m_qpaIncludeDir } },
+ { "-rhiIncludeDir", { &m_rhiIncludeDir } },
+ { "-ssgIncludeDir", { &m_ssgIncludeDir } },
+ { "-stagingDir", { &m_stagingDir, true } },
+ { "-versionScript", { &m_versionScriptFile, true } },
+ { "-publicNamespaceFilter", { &publicNamespaceFilter, true } },
+ };
+
+ static const std::unordered_map<std::string, CommandLineOption<std::set<std::string>>>
+ listArgumentMap = {
+ { "-headers", { &m_headers, true } },
+ { "-generatedHeaders", { &m_generatedHeaders, true } },
+ { "-knownModules", { &m_knownModules, true } },
+ };
+
+ static const std::unordered_map<std::string, CommandLineOption<bool>> boolArgumentMap = {
+ { "-nonQt", { &m_isNonQtModule, true } }, { "-debug", { &m_debug, true } },
+ { "-help", { &m_printHelpOnly, true } },
+ { "-internal", { &m_isInternal, true } }, { "-all", { &m_scanAllMode, true } },
+ { "-copy", { &m_copy, true } }, { "-minimal", { &m_minimal, true } },
+ { "-showonly", { &m_showOnly, true } }, { "-showOnly", { &m_showOnly, true } },
+ { "-warningsAreErrors", { &m_warningsAreErrors, true } }
+ };
+
+ std::string *currentValue = nullptr;
+ std::set<std::string> *currentListValue = nullptr;
+
+ auto parseArgument = [&currentValue, &currentListValue](const std::string &arg) -> bool {
+ if (arg[0] == '-') {
+ currentValue = nullptr;
+ currentListValue = nullptr;
+ {
+ auto it = stringArgumentMap.find(arg);
+ if (it != stringArgumentMap.end()) {
+ if (it->second.value == nullptr) {
+ utils::printInternalError();
+ return false;
+ }
+ currentValue = it->second.value;
+ return true;
+ }
+ }
+
+ {
+ auto it = boolArgumentMap.find(arg);
+ if (it != boolArgumentMap.end()) {
+ if (it->second.value == nullptr) {
+ utils::printInternalError();
+ return false;
+ }
+ *(it->second.value) = true;
+ return true;
+ }
+ }
+
+ {
+ auto it = listArgumentMap.find(arg);
+ if (it != listArgumentMap.end()) {
+ if (it->second.value == nullptr) {
+ utils::printInternalError();
+ return false;
+ }
+ currentListValue = it->second.value;
+ currentListValue->insert(""); // Indicate that argument is provided
+ return true;
+ }
+ }
+
+ std::cerr << "Unknown argument: " << arg << std::endl;
+ return false;
+ }
+
+ if (currentValue != nullptr) {
+ *currentValue = arg;
+ currentValue = nullptr;
+ } else if (currentListValue != nullptr) {
+ currentListValue->insert(arg);
+ } else {
+ std::cerr << "Unknown argument: " << arg << std::endl;
+ return false;
+ }
+ return true;
+ };
+
+ for (int i = 1; i < argc; ++i) {
+ std::string arg(argv[i]);
+ if (arg.empty())
+ continue;
+
+ if (arg[0] == '@') {
+ std::ifstream ifs(arg.substr(1), std::ifstream::in);
+ if (!ifs.is_open()) {
+ std::cerr << "Unable to open rsp file: " << arg[0] << std::endl;
+ return false;
+ }
+ std::string argFromFile;
+ while (std::getline(ifs, argFromFile)) {
+ if (argFromFile.empty())
+ continue;
+ if (!parseArgument(argFromFile))
+ return false;
+ }
+ ifs.close();
+ continue;
+ }
+
+ if (!parseArgument(arg))
+ return false;
+ }
+
+ if (m_printHelpOnly)
+ return true;
+
+ if (!qpaHeadersFilter.empty())
+ m_qpaHeadersRegex = std::regex(qpaHeadersFilter);
+
+ if (!rhiHeadersFilter.empty())
+ m_rhiHeadersRegex = std::regex(rhiHeadersFilter);
+
+ if (!ssgHeadersFilter.empty())
+ m_ssgHeadersRegex = std::regex(ssgHeadersFilter);
+
+ if (!privateHeadersFilter.empty())
+ m_privateHeadersRegex = std::regex(privateHeadersFilter);
+
+ if (!publicNamespaceFilter.empty())
+ m_publicNamespaceRegex = std::regex(publicNamespaceFilter);
+
+ if (m_headers.empty() && !m_scanAllMode) {
+ std::cerr << "You need to specify either -headers or -all option." << std::endl;
+ return false;
+ }
+
+ if (!m_headers.empty() && m_scanAllMode) {
+ std::cerr << "Both -headers and -all are specified. Need to choose only one"
+ "operational mode." << std::endl;
+ return false;
+ }
+
+ for (const auto &argument : listArgumentMap)
+ argument.second.value->erase("");
+
+ bool ret = true;
+ ret &= checkRequiredArguments(stringArgumentMap);
+ ret &= checkRequiredArguments(listArgumentMap);
+
+ normilizePaths();
+
+ return ret;
+ }
+
+ // Convert all paths from command line to a generic one.
+ void normilizePaths()
+ {
+ static std::array<std::string *, 8> paths = {
+ &m_sourceDir, &m_binaryDir, &m_includeDir, &m_privateIncludeDir,
+ &m_qpaIncludeDir, &m_rhiIncludeDir, &m_stagingDir,
+ &m_versionScriptFile,
+ };
+ for (auto path : paths) {
+ if (!path->empty())
+ *path = utils::normilizedPath(*path).generic_string();
+ }
+ }
+
+ std::string m_moduleName;
+ std::string m_sourceDir;
+ std::string m_binaryDir;
+ std::string m_includeDir;
+ std::string m_privateIncludeDir;
+ std::string m_qpaIncludeDir;
+ std::string m_rhiIncludeDir;
+ std::string m_ssgIncludeDir;
+ std::string m_stagingDir;
+ std::string m_versionScriptFile;
+ std::set<std::string> m_knownModules;
+ std::set<std::string> m_headers;
+ std::set<std::string> m_generatedHeaders;
+ bool m_scanAllMode = false;
+ bool m_copy = false;
+ bool m_isNonQtModule = false;
+ bool m_isInternal = false;
+ bool m_printHelpOnly = false;
+ bool m_debug = false;
+ bool m_minimal = false;
+ bool m_showOnly = false;
+ bool m_warningsAreErrors = false;
+ std::regex m_qpaHeadersRegex;
+ std::regex m_rhiHeadersRegex;
+ std::regex m_ssgHeadersRegex;
+ std::regex m_privateHeadersRegex;
+ std::regex m_publicNamespaceRegex;
+
+ bool m_isValid;
+};
+
+class SyncScanner
+{
+ class SymbolDescriptor
+ {
+ public:
+ // Where the symbol comes from
+ enum SourceType {
+ Pragma = 0, // pragma qt_class is mentioned a header file
+ Declaration, // The symbol declaration inside a header file
+ MaxSourceType
+ };
+
+ void update(const std::string &file, SourceType type)
+ {
+ if (type < m_type) {
+ m_file = file;
+ m_type = type;
+ }
+ }
+
+ // The file that contains a symbol.
+ const std::string &file() const { return m_file; }
+
+ private:
+ SourceType m_type = MaxSourceType;
+ std::string m_file;
+ };
+ using SymbolContainer = std::unordered_map<std::string, SymbolDescriptor>;
+
+ struct ParsingResult
+ {
+ std::vector<std::string> versionScriptContent;
+ std::string requireConfig;
+ bool masterInclude = true;
+ };
+
+ CommandLineOptions *m_commandLineArgs = nullptr;
+
+ std::map<std::string /* header file name */, std::string /* header feature guard name */,
+ decltype(MasterHeaderIncludeComparator) *>
+ m_masterHeaderContents;
+
+ std::unordered_map<std::string /* the deprecated header name*/,
+ std::string /* the replacement */>
+ m_deprecatedHeaders;
+ std::vector<std::string> m_versionScriptContents;
+ std::set<std::string> m_producedHeaders;
+ std::vector<std::string> m_headerCheckExceptions;
+ SymbolContainer m_symbols;
+ std::ostream &scannerDebug() const
+ {
+ if (m_commandLineArgs->debug())
+ return std::cout;
+ return utils::DummyOutput;
+ }
+
+ enum { Active, Stopped, IgnoreNext, Ignore } m_versionScriptGeneratorState = Active;
+
+ std::filesystem::path m_outputRootName;
+ std::filesystem::path m_currentFile;
+ std::string m_currentFilename;
+ std::string m_currentFileString;
+ size_t m_currentFileLineNumber = 0;
+ bool m_currentFileInSourceDir = false;
+
+ enum FileType { PublicHeader = 0, PrivateHeader = 1, QpaHeader = 2, ExportHeader = 4, RhiHeader = 8, SsgHeader = 16 };
+ unsigned int m_currentFileType = PublicHeader;
+
+ int m_criticalChecks = CriticalChecks;
+ std::string_view m_warningMessagePreamble;
+
+public:
+ SyncScanner(CommandLineOptions *commandLineArgs)
+ : m_commandLineArgs(commandLineArgs),
+ m_masterHeaderContents(MasterHeaderIncludeComparator),
+ m_outputRootName(
+ std::filesystem::weakly_canonical(m_commandLineArgs->includeDir()).root_name()),
+ m_warningMessagePreamble(WarningMessagePreamble)
+ {
+ }
+
+ // The function converts the relative path to a header files to the absolute. It also makes the
+ // path canonical(removes '..' and '.' parts of the path). The source directory passed in
+ // '-sourceDir' command line argument is used as base path for relative paths to create the
+ // absolute path.
+ [[nodiscard]] std::filesystem::path makeHeaderAbsolute(const std::string &filename) const;
+
+ ErrorCodes sync()
+ {
+ if (m_commandLineArgs->warningsAreErrors()) {
+ m_criticalChecks = AllChecks;
+ m_warningMessagePreamble = ErrorMessagePreamble;
+ }
+
+ m_versionScriptGeneratorState =
+ m_commandLineArgs->versionScriptFile().empty() ? Stopped : Active;
+ auto error = NoError;
+
+ // In the scan all mode we ingore the list of header files that is specified in the
+ // '-headers' argument, and collect header files from the source directory tree.
+ if (m_commandLineArgs->scanAllMode()) {
+ for (auto const &entry :
+ std::filesystem::recursive_directory_iterator(m_commandLineArgs->sourceDir())) {
+
+ const bool isRegularFile = entry.is_regular_file();
+ const bool isHeaderFlag = isHeader(entry);
+ const bool isDocFileHeuristicFlag =
+ isDocFileHeuristic(entry.path().generic_string());
+ const bool shouldProcessHeader =
+ isRegularFile && isHeaderFlag && !isDocFileHeuristicFlag;
+ const std::string filePath = entry.path().generic_string();
+
+ if (shouldProcessHeader) {
+ scannerDebug() << "Processing header: " << filePath << std::endl;
+ if (!processHeader(makeHeaderAbsolute(filePath)))
+ error = SyncFailed;
+ } else {
+ scannerDebug()
+ << "Skipping processing header: " << filePath
+ << " isRegularFile: " << isRegularFile
+ << " isHeaderFlag: " << isHeaderFlag
+ << " isDocFileHeuristicFlag: " << isDocFileHeuristicFlag
+ << std::endl;
+ }
+ }
+ } else {
+ // Since the list of header file is quite big syncqt supports response files to avoid
+ // the issues with long command lines.
+ std::set<std::string> rspHeaders;
+ const auto &headers = m_commandLineArgs->headers();
+ for (auto it = headers.begin(); it != headers.end(); ++it) {
+ const auto &header = *it;
+ scannerDebug() << "Processing header: " << header << std::endl;
+ if (!processHeader(makeHeaderAbsolute(header))) {
+ error = SyncFailed;
+ }
+ }
+ for (const auto &header : rspHeaders) {
+ scannerDebug() << "Processing header: " << header << std::endl;
+ if (!processHeader(makeHeaderAbsolute(header)))
+ error = SyncFailed;
+ }
+ }
+
+ // No further processing in minimal mode.
+ if (m_commandLineArgs->minimal())
+ return error;
+
+ // Generate aliases for all unique symbols collected during the header files parsing.
+ for (auto it = m_symbols.begin(); it != m_symbols.end(); ++it) {
+ const std::string &filename = it->second.file();
+ if (!filename.empty()) {
+ if (generateQtCamelCaseFileIfContentChanged(
+ m_commandLineArgs->includeDir() + '/' + it->first, filename)) {
+ m_producedHeaders.insert(it->first);
+ } else {
+ error = SyncFailed;
+ }
+ }
+ }
+
+ // Generate the header file containing version information.
+ if (!m_commandLineArgs->isNonQtModule()) {
+ std::string moduleNameLower = utils::asciiToLower(m_commandLineArgs->moduleName());
+ std::string versionHeaderFilename(moduleNameLower + "version.h");
+ std::string versionHeaderCamel(m_commandLineArgs->moduleName() + "Version");
+ std::string versionFile = m_commandLineArgs->includeDir() + '/' + versionHeaderFilename;
+
+ std::error_code ec;
+ FileStamp originalStamp = std::filesystem::last_write_time(versionFile, ec);
+ if (ec)
+ originalStamp = FileStamp::clock::now();
+
+ if (generateVersionHeader(versionFile)) {
+ if (!generateAliasedHeaderFileIfTimestampChanged(
+ m_commandLineArgs->includeDir() + '/' + versionHeaderCamel,
+ versionHeaderFilename, originalStamp)) {
+ error = SyncFailed;
+ }
+ m_masterHeaderContents[versionHeaderFilename] = {};
+ m_producedHeaders.insert(versionHeaderFilename);
+ m_producedHeaders.insert(versionHeaderCamel);
+ } else {
+ error = SyncFailed;
+ }
+ }
+
+ if (!m_commandLineArgs->scanAllMode()) {
+ if (!m_commandLineArgs->isNonQtModule()) {
+ if (!generateDeprecatedHeaders())
+ error = SyncFailed;
+
+ if (!generateHeaderCheckExceptions())
+ error = SyncFailed;
+ }
+
+ if (!m_commandLineArgs->versionScriptFile().empty()) {
+ if (!generateLinkerVersionScript())
+ error = SyncFailed;
+ }
+ }
+
+ if (!m_commandLineArgs->isNonQtModule()) {
+ if (!generateMasterHeader())
+ error = SyncFailed;
+ }
+
+ if (!m_commandLineArgs->scanAllMode() && !m_commandLineArgs->stagingDir().empty()) {
+ // Copy the generated files to a spearate staging directory to make the installation
+ // process eaiser.
+ if (!copyGeneratedHeadersToStagingDirectory(m_commandLineArgs->stagingDir()))
+ error = SyncFailed;
+ }
+ return error;
+ }
+
+ // The function copies files, that were generated while the sync procedure to a staging
+ // directory. This is necessary to simplify the installation of the generated files.
+ [[nodiscard]] bool copyGeneratedHeadersToStagingDirectory(const std::string &outputDirectory,
+ bool skipCleanup = false)
+ {
+ bool result = true;
+ bool outDirExists = false;
+ if (!utils::createDirectories(outputDirectory, "Unable to create staging directory",
+ &outDirExists))
+ return false;
+
+ if (outDirExists && !skipCleanup) {
+ try {
+ for (const auto &entry :
+ std::filesystem::recursive_directory_iterator(outputDirectory)) {
+ if (m_producedHeaders.find(entry.path().filename().generic_string())
+ == m_producedHeaders.end()) {
+ // Check if header file came from another module as result of the
+ // cross-module deprecation before removing it.
+ std::string firstLine;
+ {
+ std::ifstream input(entry.path(), std::ifstream::in);
+ if (input.is_open()) {
+ std::getline(input, firstLine);
+ input.close();
+ }
+ }
+ if (firstLine.find("#ifndef DEPRECATED_HEADER_"
+ + m_commandLineArgs->moduleName())
+ == 0
+ || firstLine.find("#ifndef DEPRECATED_HEADER_") != 0)
+ std::filesystem::remove(entry.path());
+ }
+ }
+ } catch (const std::filesystem::filesystem_error &fserr) {
+ utils::printFilesystemError(fserr, "Unable to clean the staging directory");
+ return false;
+ }
+ }
+
+ for (const auto &header : m_producedHeaders) {
+ std::filesystem::path src(m_commandLineArgs->includeDir() + '/' + header);
+ std::filesystem::path dst(outputDirectory + '/' + header);
+ if (!m_commandLineArgs->showOnly())
+ result &= updateOrCopy(src, dst);
+ }
+ return result;
+ }
+
+ void resetCurrentFileInfoData(const std::filesystem::path &headerFile)
+ {
+ // This regex filters the generated '*exports.h' and '*exports_p.h' header files.
+ static const std::regex ExportsHeaderRegex("^q(.*)exports(_p)?\\.h$");
+
+ m_currentFile = headerFile;
+ m_currentFileLineNumber = 0;
+ m_currentFilename = m_currentFile.filename().generic_string();
+ m_currentFileType = PublicHeader;
+ m_currentFileString = m_currentFile.generic_string();
+ m_currentFileInSourceDir = m_currentFileString.find(m_commandLineArgs->sourceDir()) == 0;
+
+ if (isHeaderPrivate(m_currentFilename))
+ m_currentFileType = PrivateHeader;
+
+ if (isHeaderQpa(m_currentFilename))
+ m_currentFileType = QpaHeader | PrivateHeader;
+
+ if (isHeaderRhi(m_currentFilename))
+ m_currentFileType = RhiHeader | PrivateHeader;
+
+ if (isHeaderSsg(m_currentFilename))
+ m_currentFileType = SsgHeader | PrivateHeader;
+
+ if (std::regex_match(m_currentFilename, ExportsHeaderRegex))
+ m_currentFileType |= ExportHeader;
+ }
+
+ [[nodiscard]] bool processHeader(const std::filesystem::path &headerFile)
+ {
+ // This regex filters any paths that contain the '3rdparty' directory.
+ static const std::regex ThirdPartyFolderRegex("(^|.+/)3rdparty/.+");
+
+ // This regex filters '-config.h' and '-config_p.h' header files.
+ static const std::regex ConfigHeaderRegex("^(q|.+-)config(_p)?\\.h");
+
+ resetCurrentFileInfoData(headerFile);
+ // We assume that header files ouside of the module source or build directories do not
+ // belong to the module. Skip any processing.
+ if (!m_currentFileInSourceDir
+ && m_currentFileString.find(m_commandLineArgs->binaryDir()) != 0) {
+ scannerDebug() << "Header file: " << headerFile
+ << " is outside the sync directories. Skipping." << std::endl;
+ m_headerCheckExceptions.push_back(m_currentFileString);
+ return true;
+ }
+
+ // Check if a directory is passed as argument. That shouldn't happen, print error and exit.
+ if (m_currentFilename.empty()) {
+ std::cerr << "Header file name of " << m_currentFileString << "is empty" << std::endl;
+ return false;
+ }
+
+ std::error_code ec;
+ FileStamp originalStamp = std::filesystem::last_write_time(headerFile, ec);
+ if (ec)
+ originalStamp = FileStamp::clock::now();
+ ec.clear();
+
+ bool isPrivate = m_currentFileType & PrivateHeader;
+ bool isQpa = m_currentFileType & QpaHeader;
+ bool isRhi = m_currentFileType & RhiHeader;
+ bool isSsg = m_currentFileType & SsgHeader;
+ bool isExport = m_currentFileType & ExportHeader;
+ scannerDebug()
+ << "processHeader:start: " << headerFile
+ << " m_currentFilename: " << m_currentFilename
+ << " isPrivate: " << isPrivate
+ << " isQpa: " << isQpa
+ << " isRhi: " << isRhi
+ << " isSsg: " << isSsg
+ << std::endl;
+
+ // Chose the directory where to generate the header aliases or to copy header file if
+ // the '-copy' argument is passed.
+ std::string outputDir = m_commandLineArgs->includeDir();
+ if (isQpa)
+ outputDir = m_commandLineArgs->qpaIncludeDir();
+ else if (isRhi)
+ outputDir = m_commandLineArgs->rhiIncludeDir();
+ else if (isSsg)
+ outputDir = m_commandLineArgs->ssgIncludeDir();
+ else if (isPrivate)
+ outputDir = m_commandLineArgs->privateIncludeDir();
+
+ if (!utils::createDirectories(outputDir, "Unable to create output directory"))
+ return false;
+
+ bool headerFileExists = std::filesystem::exists(headerFile);
+
+ std::string aliasedFilepath = headerFile.generic_string();
+
+ std::string aliasPath = outputDir + '/' + m_currentFilename;
+
+ // If the '-copy' argument is passed, we copy the original file to a corresponding output
+ // directory otherwise we only create a header file alias that contains relative path to
+ // the original header file in the module source or build tree.
+ if (m_commandLineArgs->copy() && headerFileExists) {
+ if (!updateOrCopy(headerFile, aliasPath))
+ return false;
+ } else {
+ if (!generateAliasedHeaderFileIfTimestampChanged(aliasPath, aliasedFilepath,
+ originalStamp))
+ return false;
+ }
+
+ // No further processing in minimal mode.
+ if (m_commandLineArgs->minimal())
+ return true;
+
+ // Stop processing if header files doesn't exist. This happens at configure time, since
+ // either header files are generated later than syncqt is running or header files only
+ // generated at build time. These files will be processed at build time, if CMake files
+ // contain the correct dependencies between the missing header files and the module
+ // 'sync_headers' targets.
+ if (!headerFileExists) {
+ scannerDebug() << "Header file: " << headerFile
+ << " doesn't exist, but is added to syncqt scanning. Skipping.";
+ return true;
+ }
+
+ bool isGenerated = isHeaderGenerated(m_currentFileString);
+
+ // Make sure that we detect the '3rdparty' directory inside the source directory only,
+ // since full path to the Qt sources might contain '/3rdparty/' too.
+ bool is3rdParty = std::regex_match(
+ std::filesystem::relative(headerFile, m_commandLineArgs->sourceDir())
+ .generic_string(),
+ ThirdPartyFolderRegex);
+
+ // No processing of generated Qt config header files.
+ if (!std::regex_match(m_currentFilename, ConfigHeaderRegex)) {
+ unsigned int skipChecks = m_commandLineArgs->scanAllMode() ? AllChecks : NoChecks;
+
+ // Collect checks that should skipped for the header file.
+ if (m_commandLineArgs->isNonQtModule() || is3rdParty || isQpa || isRhi || isSsg
+ || !m_currentFileInSourceDir || isGenerated) {
+ skipChecks = AllChecks;
+ } else {
+ if (std::regex_match(m_currentFilename, GlobalHeaderRegex) || isExport)
+ skipChecks |= NamespaceChecks;
+
+ if (isHeaderPCH(m_currentFilename))
+ skipChecks |= WeMeantItChecks;
+
+ if (isPrivate) {
+ skipChecks |= NamespaceChecks;
+ skipChecks |= PrivateHeaderChecks;
+ skipChecks |= IncludeChecks;
+ } else {
+ skipChecks |= WeMeantItChecks;
+ }
+ }
+
+ ParsingResult parsingResult;
+ parsingResult.masterInclude = m_currentFileInSourceDir && !isExport && !is3rdParty
+ && !isQpa && !isRhi && !isSsg && !isPrivate && !isGenerated;
+ if (!parseHeader(headerFile, parsingResult, skipChecks)) {
+ scannerDebug() << "parseHeader failed: " << headerFile << std::endl;
+ return false;
+ }
+
+ // Record the private header file inside the version script content.
+ if (isPrivate && !m_commandLineArgs->versionScriptFile().empty()
+ && !parsingResult.versionScriptContent.empty()) {
+ m_versionScriptContents.insert(m_versionScriptContents.end(),
+ parsingResult.versionScriptContent.begin(),
+ parsingResult.versionScriptContent.end());
+ }
+
+ // Add the '#if QT_CONFIG(<feature>)' check for header files that supposed to be
+ // included into the module master header only if corresponding feature is enabled.
+ bool willBeInModuleMasterHeader = false;
+ if (!isQpa && !isRhi && !isSsg && !isPrivate) {
+ if (m_currentFilename.find('_') == std::string::npos
+ && parsingResult.masterInclude) {
+ m_masterHeaderContents[m_currentFilename] = parsingResult.requireConfig;
+ willBeInModuleMasterHeader = true;
+ }
+ }
+
+ scannerDebug()
+ << "processHeader:end: " << headerFile
+ << " is3rdParty: " << is3rdParty
+ << " isGenerated: " << isGenerated
+ << " m_currentFileInSourceDir: " << m_currentFileInSourceDir
+ << " willBeInModuleMasterHeader: " << willBeInModuleMasterHeader
+ << std::endl;
+ } else if (m_currentFilename == "qconfig.h") {
+ // Hardcode generating of QtConfig alias
+ updateSymbolDescriptor("QtConfig", "qconfig.h", SyncScanner::SymbolDescriptor::Pragma);
+ }
+
+ return true;
+ }
+
+ void parseVersionScriptContent(const std::string buffer, ParsingResult &result)
+ {
+ // This regex looks for the symbols that needs to be placed into linker version script.
+ static const std::regex VersionScriptSymbolRegex(
+ "^(?:struct|class)(?:\\s+Q_\\w*_EXPORT)?\\s+([\\w:]+)[^;]*(;$)?");
+
+ // This regex looks for the namespaces that needs to be placed into linker version script.
+ static const std::regex VersionScriptNamespaceRegex(
+ "^namespace\\s+Q_\\w+_EXPORT\\s+([\\w:]+).*");
+
+ // This regex filters the tailing colon from the symbol name.
+ static const std::regex TrailingColonRegex("([\\w]+):$");
+
+ switch (m_versionScriptGeneratorState) {
+ case Ignore:
+ scannerDebug() << "line ignored: " << buffer << std::endl;
+ m_versionScriptGeneratorState = Active;
+ return;
+ case Stopped:
+ return;
+ case IgnoreNext:
+ m_versionScriptGeneratorState = Ignore;
+ break;
+ case Active:
+ break;
+ }
+
+ if (buffer.empty())
+ return;
+
+ std::smatch match;
+ std::string symbol;
+ if (std::regex_match(buffer, match, VersionScriptSymbolRegex) && match[2].str().empty())
+ symbol = match[1].str();
+ else if (std::regex_match(buffer, match, VersionScriptNamespaceRegex))
+ symbol = match[1].str();
+
+ if (std::regex_match(symbol, match, TrailingColonRegex))
+ symbol = match[1].str();
+
+ // checkLineForSymbols(buffer, symbol);
+ if (!symbol.empty() && symbol[symbol.size() - 1] != ';') {
+ std::string relPath = m_currentFileInSourceDir
+ ? std::filesystem::relative(m_currentFile, m_commandLineArgs->sourceDir())
+ .string()
+ : std::filesystem::relative(m_currentFile, m_commandLineArgs->binaryDir())
+ .string();
+
+ std::string versionStringRecord = " *";
+ size_t startPos = 0;
+ size_t endPos = 0;
+ while (endPos != std::string::npos) {
+ endPos = symbol.find("::", startPos);
+ size_t length = endPos != std::string::npos ? (endPos - startPos)
+ : (symbol.size() - startPos);
+ if (length > 0) {
+ std::string symbolPart = symbol.substr(startPos, length);
+ versionStringRecord += std::to_string(symbolPart.size());
+ versionStringRecord += symbolPart;
+ }
+ startPos = endPos + 2;
+ }
+ versionStringRecord += "*;";
+ if (versionStringRecord.size() < LinkerScriptCommentAlignment)
+ versionStringRecord +=
+ std::string(LinkerScriptCommentAlignment - versionStringRecord.size(), ' ');
+ versionStringRecord += " # ";
+ versionStringRecord += relPath;
+ versionStringRecord += ":";
+ versionStringRecord += std::to_string(m_currentFileLineNumber);
+ versionStringRecord += "\n";
+ result.versionScriptContent.push_back(versionStringRecord);
+ }
+ }
+
+ // The function parses 'headerFile' and collect artifacts that are used at generating step.
+ // 'timeStamp' is saved in internal structures to compare it when generating files.
+ // 'result' the function output value that stores the result of parsing.
+ // 'skipChecks' checks that are not applicable for the header file.
+ [[nodiscard]] bool parseHeader(const std::filesystem::path &headerFile,
+ ParsingResult &result,
+ unsigned int skipChecks)
+ {
+ if (m_commandLineArgs->showOnly())
+ std::cout << headerFile << " [" << m_commandLineArgs->moduleName() << "]" << std::endl;
+ // This regex checks if line contains a macro.
+ static const std::regex MacroRegex("^\\s*#.*");
+
+ // The regex's bellow check line for known pragmas:
+ //
+ // - 'once' is not allowed in installed headers, so error out.
+ //
+ // - 'qt_sync_skip_header_check' avoid any header checks.
+ //
+ // - 'qt_sync_stop_processing' stops the header proccesing from a moment when pragma is
+ // found. Important note: All the parsing artifacts were found before this point are
+ // stored for further processing.
+ //
+ // - 'qt_sync_suspend_processing' pauses processing and skip lines inside a header until
+ // 'qt_sync_resume_processing' is found. 'qt_sync_stop_processing' stops processing if
+ // it's found before the 'qt_sync_resume_processing'.
+ //
+ // - 'qt_sync_resume_processing' resumes processing after 'qt_sync_suspend_processing'.
+ //
+ // - 'qt_class(<symbol>)' manually declares the 'symbol' that should be used to generate
+ // the CaMeL case header alias.
+ //
+ // - 'qt_deprecates([module/]<deprecated header file>[,<major.minor>])' indicates that
+ // this header file replaces the 'deprecated header file'. syncqt will create the
+ // deprecated header file' with the special deprecation content. Pragma optionally
+ // accepts the Qt version where file should be removed. If the current Qt version is
+ // higher than the deprecation version, syncqt displays deprecation warning and skips
+ // generating the deprecated header. If the module is specified and is different from
+ // the one this header file belongs to, syncqt attempts to generate header files
+ // for the specified module. Cross-module deprecation only works within the same repo.
+ // See the 'generateDeprecatedHeaders' function for details.
+ //
+ // - 'qt_no_master_include' indicates that syncqt should avoid including this header
+ // files into the module master header file.
+ static const std::regex OnceRegex(R"(^#\s*pragma\s+once$)");
+ static const std::regex SkipHeaderCheckRegex("^#\\s*pragma qt_sync_skip_header_check$");
+ static const std::regex StopProcessingRegex("^#\\s*pragma qt_sync_stop_processing$");
+ static const std::regex SuspendProcessingRegex("^#\\s*pragma qt_sync_suspend_processing$");
+ static const std::regex ResumeProcessingRegex("^#\\s*pragma qt_sync_resume_processing$");
+ static const std::regex ExplixitClassPragmaRegex("^#\\s*pragma qt_class\\(([^\\)]+)\\)$");
+ static const std::regex DeprecatesPragmaRegex("^#\\s*pragma qt_deprecates\\(([^\\)]+)\\)$");
+ static const std::regex NoMasterIncludePragmaRegex("^#\\s*pragma qt_no_master_include$");
+
+ // This regex checks if header contains 'We mean it' disclaimer. All private headers should
+ // contain them.
+ static const std::string_view WeMeantItString("We mean it.");
+
+ // The regex's check if the content of header files is wrapped with the Qt namespace macros.
+ static const std::regex BeginNamespaceRegex("^QT_BEGIN_NAMESPACE(_[A-Z_]+)?$");
+ static const std::regex EndNamespaceRegex("^QT_END_NAMESPACE(_[A-Z_]+)?$");
+
+ // This regex checks if line contains the include macro of the following formats:
+ // - #include <file>
+ // - #include "file"
+ // - # include <file>
+ static const std::regex IncludeRegex("^#\\s*include\\s*[<\"](.+)[>\"]");
+
+ // This regex checks if line contains namespace definition.
+ static const std::regex NamespaceRegex("\\s*namespace ([^ ]*)\\s+");
+
+ // This regex checks if line contains the Qt iterator declaration, that need to have
+ // CaMel case header alias.
+ static const std::regex DeclareIteratorRegex("^ *Q_DECLARE_\\w*ITERATOR\\((\\w+)\\);?$");
+
+ // This regex checks if header file contains the QT_REQUIRE_CONFIG call.
+ // The macro argument is used to wrap an include of the header file inside the module master
+ // header file with the '#if QT_CONFIG(<feature>)' guard.
+ static const std::regex RequireConfigRegex("^ *QT_REQUIRE_CONFIG\\((\\w+)\\);?$");
+
+ // This regex looks for the ELFVERSION tag this is control key-word for the version script
+ // content processing.
+ // ELFVERSION tag accepts the following values:
+ // - stop - stops the symbols lookup for a version script starting from this line.
+ // - ignore-next - ignores the line followed by the current one.
+ // - ignore - ignores the current line.
+ static const std::regex ElfVersionTagRegex(".*ELFVERSION:(stop|ignore-next|ignore).*");
+
+ std::ifstream input(headerFile, std::ifstream::in);
+ if (!input.is_open()) {
+ std::cerr << "Unable to open " << headerFile << std::endl;
+ return false;
+ }
+
+ bool hasQtBeginNamespace = false;
+ std::string qtBeginNamespace;
+ std::string qtEndNamespace;
+ bool hasWeMeantIt = false;
+ bool isSuspended = false;
+ bool isMultiLineComment = false;
+ std::size_t bracesDepth = 0;
+ std::size_t namespaceCount = 0;
+ std::string namespaceString;
+
+ std::smatch match;
+
+ std::string buffer;
+ std::string line;
+ std::string tmpLine;
+ std::size_t linesProcessed = 0;
+ int faults = NoChecks;
+
+ const auto error = [&] () -> decltype(auto) {
+ return std::cerr << ErrorMessagePreamble << m_currentFileString
+ << ":" << m_currentFileLineNumber << " ";
+ };
+
+ // Read file line by line
+ while (std::getline(input, tmpLine)) {
+ ++m_currentFileLineNumber;
+ line.append(tmpLine);
+ if (line.empty() || line.at(line.size() - 1) == '\\') {
+ continue;
+ }
+ buffer.clear();
+ buffer.reserve(line.size());
+ // Optimize processing by looking for a special sequences such as:
+ // - start-end of comments
+ // - start-end of class/structures
+ // And avoid processing of the the data inside these blocks.
+ for (std::size_t i = 0; i < line.size(); ++i) {
+ if (line[i] == '\r')
+ continue;
+ if (bracesDepth == namespaceCount) {
+ if (line[i] == '/') {
+ if ((i + 1) < line.size()) {
+ if (line[i + 1] == '*') {
+ isMultiLineComment = true;
+ continue;
+ } else if (line[i + 1] == '/') { // Single line comment
+ if (!(skipChecks & WeMeantItChecks)
+ && line.find(WeMeantItString) != std::string::npos) {
+ hasWeMeantIt = true;
+ continue;
+ }
+ if (m_versionScriptGeneratorState != Stopped
+ && std::regex_match(line, match, ElfVersionTagRegex)) {
+ if (match[1].str() == "ignore")
+ m_versionScriptGeneratorState = Ignore;
+ else if (match[1].str() == "ignore-next")
+ m_versionScriptGeneratorState = IgnoreNext;
+ else if (match[1].str() == "stop")
+ m_versionScriptGeneratorState = Stopped;
+ }
+ break;
+ }
+ }
+ } else if (line[i] == '*' && (i + 1) < line.size() && line[i + 1] == '/') {
+ ++i;
+ isMultiLineComment = false;
+ continue;
+ }
+ }
+
+ if (isMultiLineComment) {
+ if (!(skipChecks & WeMeantItChecks) &&
+ line.find(WeMeantItString) != std::string::npos) {
+ hasWeMeantIt = true;
+ continue;
+ }
+ continue;
+ }
+
+ if (line[i] == '{') {
+ if (std::regex_match(buffer, match, NamespaceRegex)) {
+ ++namespaceCount;
+ namespaceString += "::";
+ namespaceString += match[1].str();
+ }
+ ++bracesDepth;
+ continue;
+ } else if (line[i] == '}') {
+ if (namespaceCount > 0 && bracesDepth == namespaceCount) {
+ namespaceString.resize(namespaceString.rfind("::"));
+ --namespaceCount;
+ }
+ --bracesDepth;
+ } else if (bracesDepth == namespaceCount) {
+ buffer += line[i];
+ }
+ }
+ line.clear();
+
+ scannerDebug() << m_currentFilename << ": " << buffer << std::endl;
+
+ if (m_currentFileType & PrivateHeader) {
+ parseVersionScriptContent(buffer, result);
+ }
+
+ if (buffer.empty())
+ continue;
+
+ ++linesProcessed;
+
+ bool skipSymbols =
+ (m_currentFileType & PrivateHeader) || (m_currentFileType & QpaHeader) || (m_currentFileType & RhiHeader)
+ || (m_currentFileType & SsgHeader);
+
+ // Parse pragmas
+ if (std::regex_match(buffer, MacroRegex)) {
+ if (std::regex_match(buffer, SkipHeaderCheckRegex)) {
+ skipChecks = AllChecks;
+ faults = NoChecks;
+ } else if (std::regex_match(buffer, StopProcessingRegex)) {
+ if (skipChecks == AllChecks)
+ m_headerCheckExceptions.push_back(m_currentFileString);
+ return true;
+ } else if (std::regex_match(buffer, SuspendProcessingRegex)) {
+ isSuspended = true;
+ } else if (std::regex_match(buffer, ResumeProcessingRegex)) {
+ isSuspended = false;
+ } else if (std::regex_match(buffer, match, ExplixitClassPragmaRegex)) {
+ if (!skipSymbols) {
+ updateSymbolDescriptor(match[1].str(), m_currentFilename,
+ SymbolDescriptor::Pragma);
+ } else {
+ // TODO: warn about skipping symbols that are defined explicitly
+ }
+ } else if (std::regex_match(buffer, NoMasterIncludePragmaRegex)) {
+ result.masterInclude = false;
+ } else if (std::regex_match(buffer, match, DeprecatesPragmaRegex)) {
+ m_deprecatedHeaders[match[1].str()] =
+ m_commandLineArgs->moduleName() + '/' + m_currentFilename;
+ } else if (std::regex_match(buffer, OnceRegex)) {
+ if (!(skipChecks & PragmaOnceChecks)) {
+ faults |= PragmaOnceChecks;
+ error() << "\"#pragma once\" is not allowed in installed header files: "
+ "https://lists.qt-project.org/pipermail/development/2022-October/043121.html"
+ << std::endl;
+ }
+ } else if (std::regex_match(buffer, match, IncludeRegex) && !isSuspended) {
+ if (!(skipChecks & IncludeChecks)) {
+ std::string includedHeader = match[1].str();
+ if (!(skipChecks & PrivateHeaderChecks)
+ && isHeaderPrivate(std::filesystem::path(includedHeader)
+ .filename()
+ .generic_string())) {
+ faults |= PrivateHeaderChecks;
+ error() << "includes private header " << includedHeader << std::endl;
+ }
+ for (const auto &module : m_commandLineArgs->knownModules()) {
+ std::string suggestedHeader = "Qt" + module + '/' + includedHeader;
+ if (std::filesystem::exists(m_commandLineArgs->includeDir() + "/../"
+ + suggestedHeader)) {
+ faults |= IncludeChecks;
+ std::cerr << m_warningMessagePreamble << m_currentFileString
+ << ":" << m_currentFileLineNumber
+ << " includes " << includedHeader
+ << " when it should include "
+ << suggestedHeader << std::endl;
+ }
+ }
+ }
+ }
+ continue;
+ }
+
+ // Logic below this line is affected by the 'qt_sync_suspend_processing' and
+ // 'qt_sync_resume_processing' pragmas.
+ if (isSuspended)
+ continue;
+
+ // Look for the symbols in header file.
+ if (!skipSymbols) {
+ std::string symbol;
+ if (checkLineForSymbols(buffer, symbol)) {
+ if (namespaceCount == 0
+ || std::regex_match(namespaceString,
+ m_commandLineArgs->publicNamespaceRegex())) {
+ updateSymbolDescriptor(symbol, m_currentFilename,
+ SymbolDescriptor::Declaration);
+ }
+ continue;
+ } else if (std::regex_match(buffer, match, DeclareIteratorRegex)) {
+ std::string iteratorSymbol = match[1].str() + "Iterator";
+ updateSymbolDescriptor(std::string("Q") + iteratorSymbol, m_currentFilename,
+ SymbolDescriptor::Declaration);
+ updateSymbolDescriptor(std::string("QMutable") + iteratorSymbol,
+ m_currentFilename, SymbolDescriptor::Declaration);
+ continue;
+ } else if (std::regex_match(buffer, match, RequireConfigRegex)) {
+ result.requireConfig = match[1].str();
+ continue;
+ }
+ }
+
+ // Check for both QT_BEGIN_NAMESPACE and QT_END_NAMESPACE macros are present in the
+ // header file.
+ if (!(skipChecks & NamespaceChecks)) {
+ if (std::regex_match(buffer, match, BeginNamespaceRegex)) {
+ qtBeginNamespace = match[1].str();
+ hasQtBeginNamespace = true;
+ } else if (std::regex_match(buffer, match, EndNamespaceRegex)) {
+ qtEndNamespace = match[1].str();
+ }
+ }
+ }
+ input.close();
+
+ // Error out if namespace checks are failed.
+ if (!(skipChecks & NamespaceChecks)) {
+ if (hasQtBeginNamespace) {
+ if (qtBeginNamespace != qtEndNamespace) {
+ faults |= NamespaceChecks;
+ std::cerr << m_warningMessagePreamble << m_currentFileString
+ << " the begin namespace macro QT_BEGIN_NAMESPACE" << qtBeginNamespace
+ << " doesn't match the end namespace macro QT_END_NAMESPACE"
+ << qtEndNamespace << std::endl;
+ }
+ } else {
+ faults |= NamespaceChecks;
+ std::cerr << m_warningMessagePreamble << m_currentFileString
+ << " does not include QT_BEGIN_NAMESPACE" << std::endl;
+ }
+ }
+
+ if (!(skipChecks & WeMeantItChecks) && !hasWeMeantIt) {
+ faults |= WeMeantItChecks;
+ std::cerr << m_warningMessagePreamble << m_currentFileString
+ << " does not have the \"We mean it.\" warning"
+ << std::endl;
+ }
+
+ scannerDebug() << "linesTotal: " << m_currentFileLineNumber
+ << " linesProcessed: " << linesProcessed << std::endl;
+
+ if (skipChecks == AllChecks)
+ m_headerCheckExceptions.push_back(m_currentFileString);
+
+ // Exit with an error if any of critical checks are present.
+ return !(faults & m_criticalChecks);
+ }
+
+ // The function checks if line contains the symbol that needs to have a CaMeL-style alias.
+ [[nodiscard]] bool checkLineForSymbols(const std::string &line, std::string &symbol)
+ {
+ scannerDebug() << "checkLineForSymbols: " << line << std::endl;
+
+ // This regex checks if line contains class or structure declaration like:
+ // - <class|stuct> StructName
+ // - template <> class ClassName
+ // - class ClassName : [public|protected|private] BaseClassName
+ // - class ClassName [final|Q_DECL_FINAL|sealed]
+ // And possible combinations of the above variants.
+ static const std::regex ClassRegex(
+ "^ *(template *<.*> *)?(class|struct) +([^ <>]* "
+ "+)?((?!Q_DECL_FINAL|final|sealed)[^<\\s\\:]+) ?(<[^>\\:]*> "
+ "?)?\\s*(?:Q_DECL_FINAL|final|sealed)?\\s*((,|:)\\s*(public|protected|private)? "
+ "*.*)? *$");
+
+ // This regex checks if line contains function pointer typedef declaration like:
+ // - typedef void (* QFunctionPointerType)(int, char);
+ static const std::regex FunctionPointerRegex(
+ "^ *typedef *.*\\(\\*(Q[^\\)]+)\\)\\(.*\\); *");
+
+ // This regex checks if line contains class or structure typedef declaration like:
+ // - typedef AnySymbol<char> QAnySymbolType;
+ static const std::regex TypedefRegex("^ *typedef\\s+(.*)\\s+(Q\\w+); *$");
+
+ // This regex checks if symbols is the Qt public symbol. Assume that Qt public symbols start
+ // with the capital 'Q'.
+ static const std::regex QtClassRegex("^Q\\w+$");
+
+ std::smatch match;
+ if (std::regex_match(line, match, FunctionPointerRegex)) {
+ symbol = match[1].str();
+ } else if (std::regex_match(line, match, TypedefRegex)) {
+ symbol = match[2].str();
+ } else if (std::regex_match(line, match, ClassRegex)) {
+ symbol = match[4].str();
+ if (!std::regex_match(symbol, QtClassRegex))
+ symbol.clear();
+ } else {
+ return false;
+ }
+ return !symbol.empty();
+ }
+
+ [[nodiscard]] bool isHeaderQpa(const std::string &headerFileName)
+ {
+ return std::regex_match(headerFileName, m_commandLineArgs->qpaHeadersRegex());
+ }
+
+ [[nodiscard]] bool isHeaderRhi(const std::string &headerFileName)
+ {
+ return std::regex_match(headerFileName, m_commandLineArgs->rhiHeadersRegex());
+ }
+
+ [[nodiscard]] bool isHeaderSsg(const std::string &headerFileName)
+ {
+ return std::regex_match(headerFileName, m_commandLineArgs->ssgHeadersRegex());
+ }
+
+ [[nodiscard]] bool isHeaderPrivate(const std::string &headerFile)
+ {
+ return std::regex_match(headerFile, m_commandLineArgs->privateHeadersRegex());
+ }
+
+ [[nodiscard]] bool isHeaderPCH(const std::string &headerFilename)
+ {
+ static const std::string pchSuffix("_pch.h");
+ return headerFilename.find(pchSuffix, headerFilename.size() - pchSuffix.size())
+ != std::string::npos;
+ }
+
+ [[nodiscard]] bool isHeader(const std::filesystem::path &path)
+ {
+ return path.extension().string() == ".h";
+ }
+
+ [[nodiscard]] bool isDocFileHeuristic(const std::string &headerFilePath)
+ {
+ return headerFilePath.find("/doc/") != std::string::npos;
+ }
+
+ [[nodiscard]] bool isHeaderGenerated(const std::string &header)
+ {
+ return m_commandLineArgs->generatedHeaders().find(header)
+ != m_commandLineArgs->generatedHeaders().end();
+ }
+
+ [[nodiscard]] bool generateQtCamelCaseFileIfContentChanged(const std::string &outputFilePath,
+ const std::string &aliasedFilePath);
+
+ [[nodiscard]] bool generateAliasedHeaderFileIfTimestampChanged(
+ const std::string &outputFilePath, const std::string &aliasedFilePath,
+ const FileStamp &originalStamp = FileStamp::clock::now());
+
+ bool writeIfDifferent(const std::string &outputFile, const std::string &buffer);
+
+ [[nodiscard]] bool generateMasterHeader()
+ {
+ if (m_masterHeaderContents.empty())
+ return true;
+
+ std::string outputFile =
+ m_commandLineArgs->includeDir() + '/' + m_commandLineArgs->moduleName();
+
+ std::string moduleUpper = utils::asciiToUpper(m_commandLineArgs->moduleName());
+ std::stringstream buffer;
+ buffer << "#ifndef QT_" << moduleUpper << "_MODULE_H\n"
+ << "#define QT_" << moduleUpper << "_MODULE_H\n"
+ << "#include <" << m_commandLineArgs->moduleName() << "/"
+ << m_commandLineArgs->moduleName() << "Depends>\n";
+ for (const auto &headerContents : m_masterHeaderContents) {
+ if (!headerContents.second.empty()) {
+ buffer << "#if QT_CONFIG(" << headerContents.second << ")\n"
+ << "#include \"" << headerContents.first << "\"\n"
+ << "#endif\n";
+ } else {
+ buffer << "#include \"" << headerContents.first << "\"\n";
+ }
+ }
+ buffer << "#endif\n";
+
+ m_producedHeaders.insert(m_commandLineArgs->moduleName());
+ return writeIfDifferent(outputFile, buffer.str());
+ }
+
+ [[nodiscard]] bool generateVersionHeader(const std::string &outputFile)
+ {
+ std::string moduleNameUpper = utils::asciiToUpper( m_commandLineArgs->moduleName());
+
+ std::stringstream buffer;
+ buffer << "/* This file was generated by syncqt. */\n"
+ << "#ifndef QT_" << moduleNameUpper << "_VERSION_H\n"
+ << "#define QT_" << moduleNameUpper << "_VERSION_H\n\n"
+ << "#define " << moduleNameUpper << "_VERSION_STR \"" << QT_VERSION_STR << "\"\n\n"
+ << "#define " << moduleNameUpper << "_VERSION "
+ << "0x0" << QT_VERSION_MAJOR << "0" << QT_VERSION_MINOR << "0" << QT_VERSION_PATCH
+ << "\n\n"
+ << "#endif // QT_" << moduleNameUpper << "_VERSION_H\n";
+
+ return writeIfDifferent(outputFile, buffer.str());
+ }
+
+ [[nodiscard]] bool generateDeprecatedHeaders()
+ {
+ static std::regex cIdentifierSymbolsRegex("[^a-zA-Z0-9_]");
+ static std::string guard_base = "DEPRECATED_HEADER_" + m_commandLineArgs->moduleName();
+ bool result = true;
+ for (auto it = m_deprecatedHeaders.begin(); it != m_deprecatedHeaders.end(); ++it) {
+ const std::string &descriptor = it->first;
+ const std::string &replacement = it->second;
+
+ const auto separatorPos = descriptor.find(',');
+ std::string headerPath = descriptor.substr(0, separatorPos);
+ std::string versionDisclaimer;
+ if (separatorPos != std::string::npos) {
+ std::string version = descriptor.substr(separatorPos + 1);
+ versionDisclaimer = " and will be removed in Qt " + version;
+ int minor = 0;
+ int major = 0;
+ if (!utils::parseVersion(version, major, minor)) {
+ std::cerr << ErrorMessagePreamble
+ << "Invalid version format specified for the deprecated header file "
+ << headerPath << ": '" << version
+ << "'. Expected format: 'major.minor'.\n";
+ result = false;
+ continue;
+ }
+
+ if (QT_VERSION_MAJOR > major
+ || (QT_VERSION_MAJOR == major && QT_VERSION_MINOR >= minor)) {
+ std::cerr << WarningMessagePreamble << headerPath
+ << " is marked as deprecated and will not be generated in Qt "
+ << QT_VERSION_STR
+ << ". The respective qt_deprecates pragma needs to be removed.\n";
+ continue;
+ }
+ }
+
+ const auto moduleSeparatorPos = headerPath.find('/');
+ std::string headerName = moduleSeparatorPos != std::string::npos
+ ? headerPath.substr(moduleSeparatorPos + 1)
+ : headerPath;
+ const std::string moduleName = moduleSeparatorPos != std::string::npos
+ ? headerPath.substr(0, moduleSeparatorPos)
+ : m_commandLineArgs->moduleName();
+
+ bool isCrossModuleDeprecation = moduleName != m_commandLineArgs->moduleName();
+
+ std::string qualifiedHeaderName =
+ std::regex_replace(headerName, cIdentifierSymbolsRegex, "_");
+ std::string guard = guard_base + "_" + qualifiedHeaderName;
+ std::string warningText = "Header <" + moduleName + "/" + headerName + "> is deprecated"
+ + versionDisclaimer + ". Please include <" + replacement + "> instead.";
+ std::stringstream buffer;
+ buffer << "#ifndef " << guard << "\n"
+ << "#define " << guard << "\n"
+ << "#if defined(__GNUC__)\n"
+ << "# warning " << warningText << "\n"
+ << "#elif defined(_MSC_VER)\n"
+ << "# pragma message (\"" << warningText << "\")\n"
+ << "#endif\n"
+ << "#include <" << replacement << ">\n"
+ << "#endif\n";
+
+ const std::string outputDir = isCrossModuleDeprecation
+ ? m_commandLineArgs->includeDir() + "/../" + moduleName
+ : m_commandLineArgs->includeDir();
+ writeIfDifferent(outputDir + '/' + headerName, buffer.str());
+
+ // Add header file to staging installation directory for cross-module deprecation case.
+ if (isCrossModuleDeprecation) {
+ const std::string stagingDir = outputDir + "/.syncqt_staging/";
+ writeIfDifferent(stagingDir + headerName, buffer.str());
+ }
+ m_producedHeaders.insert(headerName);
+ }
+ return result;
+ }
+
+ [[nodiscard]] bool generateHeaderCheckExceptions()
+ {
+ std::stringstream buffer;
+ for (const auto &header : m_headerCheckExceptions)
+ buffer << header << ";";
+ return writeIfDifferent(m_commandLineArgs->binaryDir() + '/'
+ + m_commandLineArgs->moduleName()
+ + "_header_check_exceptions",
+ buffer.str());
+ }
+
+ [[nodiscard]] bool generateLinkerVersionScript()
+ {
+ std::stringstream buffer;
+ for (const auto &content : m_versionScriptContents)
+ buffer << content;
+ return writeIfDifferent(m_commandLineArgs->versionScriptFile(), buffer.str());
+ }
+
+ bool updateOrCopy(const std::filesystem::path &src, const std::filesystem::path &dst) noexcept;
+ void updateSymbolDescriptor(const std::string &symbol, const std::string &file,
+ SymbolDescriptor::SourceType type);
+};
+
+// The function updates information about the symbol:
+// - The path and modification time of the file where the symbol was found.
+// - The source of finding
+// Also displays a short info about a symbol in show only mode.
+void SyncScanner::updateSymbolDescriptor(const std::string &symbol, const std::string &file,
+ SymbolDescriptor::SourceType type)
+{
+ if (m_commandLineArgs->showOnly())
+ std::cout << " SYMBOL: " << symbol << std::endl;
+ m_symbols[symbol].update(file, type);
+}
+
+[[nodiscard]] std::filesystem::path
+SyncScanner::makeHeaderAbsolute(const std::string &filename) const
+{
+ if (std::filesystem::path(filename).is_relative())
+ return utils::normilizedPath(m_commandLineArgs->sourceDir() + '/' + filename);
+
+ return utils::normilizedPath(filename);
+}
+
+bool SyncScanner::updateOrCopy(const std::filesystem::path &src,
+ const std::filesystem::path &dst) noexcept
+{
+ if (m_commandLineArgs->showOnly())
+ return true;
+
+ if (src == dst) {
+ std::cout << "Source and destination paths are same when copying " << src.string()
+ << ". Skipping." << std::endl;
+ return true;
+ }
+
+ std::error_code ec;
+ std::filesystem::copy(src, dst, std::filesystem::copy_options::update_existing, ec);
+ if (ec) {
+ ec.clear();
+ std::filesystem::remove(dst, ec);
+ if (ec) {
+ // On some file systems(e.g. vboxfs) the std::filesystem::copy doesn't support
+ // std::filesystem::copy_options::overwrite_existing remove file first and then copy.
+ std::cerr << "Unable to remove file: " << src << " to " << dst << " error: ("
+ << ec.value() << ")" << ec.message() << std::endl;
+ return false;
+ }
+
+ std::filesystem::copy(src, dst, std::filesystem::copy_options::overwrite_existing, ec);
+ if (ec) {
+ std::cerr << "Unable to copy file: " << src << " to " << dst << " error: ("
+ << ec.value() << ")" << ec.message() << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+// The function generates Qt CaMeL-case files.
+// CaMeL-case files can have timestamp that is the same as or newer than timestamp of file that
+// supposed to included there. It's not an issue when we generate regular aliases because the
+// content of aliases is always the same, but we only want to "touch" them when content of original
+// is changed.
+bool SyncScanner::generateQtCamelCaseFileIfContentChanged(const std::string &outputFilePath,
+ const std::string &aliasedFilePath)
+{
+ if (m_commandLineArgs->showOnly())
+ return true;
+
+ std::string buffer = "#include \"";
+ buffer += aliasedFilePath;
+ buffer += "\" // IWYU pragma: export\n";
+
+ return writeIfDifferent(outputFilePath, buffer);
+}
+
+// The function generates aliases for files in source tree. Since the content of these aliases is
+// always same, it's ok to check only timestamp and touch files in case if stamp of original is
+// newer than the timestamp of an alias.
+bool SyncScanner::generateAliasedHeaderFileIfTimestampChanged(const std::string &outputFilePath,
+ const std::string &aliasedFilePath,
+ const FileStamp &originalStamp)
+{
+ if (m_commandLineArgs->showOnly())
+ return true;
+
+ if (std::filesystem::exists({ outputFilePath })
+ && std::filesystem::last_write_time({ outputFilePath }) >= originalStamp) {
+ return true;
+ }
+ scannerDebug() << "Rewrite " << outputFilePath << std::endl;
+
+ std::ofstream ofs;
+ ofs.open(outputFilePath, std::ofstream::out | std::ofstream::trunc);
+ if (!ofs.is_open()) {
+ std::cerr << "Unable to write header file alias: " << outputFilePath << std::endl;
+ return false;
+ }
+ ofs << "#include \"" << aliasedFilePath << "\" // IWYU pragma: export\n";
+ ofs.close();
+ return true;
+}
+
+bool SyncScanner::writeIfDifferent(const std::string &outputFile, const std::string &buffer)
+{
+ if (m_commandLineArgs->showOnly())
+ return true;
+
+ static const std::streamsize bufferSize = 1025;
+ bool differs = false;
+ std::filesystem::path outputFilePath(outputFile);
+
+ std::string outputDirectory = outputFilePath.parent_path().string();
+
+ if (!utils::createDirectories(outputDirectory, "Unable to create output directory"))
+ return false;
+
+ auto expectedSize = buffer.size();
+#ifdef _WINDOWS
+ // File on disk has \r\n instead of just \n
+ expectedSize += std::count(buffer.begin(), buffer.end(), '\n');
+#endif
+
+ if (std::filesystem::exists(outputFilePath)
+ && expectedSize == std::filesystem::file_size(outputFilePath)) {
+ char rdBuffer[bufferSize];
+ memset(rdBuffer, 0, bufferSize);
+
+ std::ifstream ifs(outputFile, std::fstream::in);
+ if (!ifs.is_open()) {
+ std::cerr << "Unable to open " << outputFile << " for comparison." << std::endl;
+ return false;
+ }
+ std::streamsize currentPos = 0;
+
+ std::size_t bytesRead = 0;
+ do {
+ ifs.read(rdBuffer, bufferSize - 1); // Read by 1K
+ bytesRead = ifs.gcount();
+ if (buffer.compare(currentPos, bytesRead, rdBuffer) != 0) {
+ differs = true;
+ break;
+ }
+ currentPos += bytesRead;
+ memset(rdBuffer, 0, bufferSize);
+ } while (bytesRead > 0);
+
+ ifs.close();
+ } else {
+ differs = true;
+ }
+
+ scannerDebug() << "Update: " << outputFile << " " << differs << std::endl;
+ if (differs) {
+ std::ofstream ofs;
+ ofs.open(outputFilePath, std::fstream::out | std::ofstream::trunc);
+ if (!ofs.is_open()) {
+ std::cerr << "Unable to write header content to " << outputFilePath << std::endl;
+ return false;
+ }
+ ofs << buffer;
+
+ ofs.close();
+ }
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ CommandLineOptions options(argc, argv);
+ if (!options.isValid())
+ return InvalidArguments;
+
+ if (options.printHelpOnly()) {
+ options.printHelp();
+ return NoError;
+ }
+
+ SyncScanner scanner = SyncScanner(&options);
+ return scanner.sync();
+}
diff --git a/src/tools/tracegen/CMakeLists.txt b/src/tools/tracegen/CMakeLists.txt
index bb45950081..f5f6b2e184 100644
--- a/src/tools/tracegen/CMakeLists.txt
+++ b/src/tools/tracegen/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from tracegen.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tracegen Tool:
@@ -6,19 +7,18 @@
qt_get_tool_target_name(target_name tracegen)
qt_internal_add_tool(${target_name}
- BOOTSTRAP
+ CORE_LIBRARY Bootstrap
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
etw.cpp etw.h
helpers.cpp helpers.h
+ ctf.cpp ctf.h
lttng.cpp lttng.h
panic.cpp panic.h
provider.cpp provider.h
qtheaders.cpp qtheaders.h
tracegen.cpp
+ NO_UNITY_BUILD
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:tracegen.pro:<TRUE>:
-# _OPTION = "host_build"
diff --git a/src/tools/tracegen/ctf.cpp b/src/tools/tracegen/ctf.cpp
new file mode 100644
index 0000000000..95ffcf89cc
--- /dev/null
+++ b/src/tools/tracegen/ctf.cpp
@@ -0,0 +1,376 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "ctf.h"
+#include "provider.h"
+#include "helpers.h"
+#include "panic.h"
+#include "qtheaders.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qdebug.h>
+
+
+static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
+{
+ writeCommonPrologue(stream);
+ const QString guard = includeGuard(fileName);
+
+ // include prefix text or qt headers only once
+ stream << "#if !defined(" << guard << ")\n";
+ stream << qtHeaders();
+ stream << "\n";
+ if (!provider.prefixText.isEmpty())
+ stream << provider.prefixText.join(u'\n') << "\n\n";
+ stream << "#endif\n\n";
+
+ /* the first guard is the usual one, the second is required
+ * by LTTNG to force the re-evaluation of TRACEPOINT_* macros
+ */
+ stream << "#if !defined(" << guard << ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n";
+
+ stream << "#define " << guard << "\n\n"
+ << "#undef TRACEPOINT_INCLUDE\n"
+ << "#define TRACEPOINT_INCLUDE \"" << fileName << "\"\n\n";
+
+ stream << "#include <private/qctf_p.h>\n\n";
+
+ const QString namespaceGuard = guard + QStringLiteral("_USE_NAMESPACE");
+ stream << "#if !defined(" << namespaceGuard << ")\n"
+ << "#define " << namespaceGuard << "\n"
+ << "QT_USE_NAMESPACE\n"
+ << "#endif // " << namespaceGuard << "\n\n";
+
+ stream << "TRACEPOINT_PROVIDER(" << provider.name << ");\n\n";
+}
+
+static void writeEpilogue(QTextStream &stream, const QString &fileName)
+{
+ stream << "\n";
+ stream << "#endif // " << includeGuard(fileName) << "\n"
+ << "#include <private/qtrace_p.h>\n";
+}
+
+static void writeWrapper(QTextStream &stream,
+ const Tracepoint &tracepoint, const Provider &provider)
+{
+ const QString argList = formatFunctionSignature(tracepoint.args);
+ const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, CTF);
+ const QString &name = tracepoint.name;
+ const QString includeGuard = QStringLiteral("TP_%1_%2").arg(provider.name).arg(name).toUpper();
+
+ /* prevents the redefinion of the inline wrapper functions
+ */
+ stream << "\n"
+ << "#ifndef " << includeGuard << "\n"
+ << "#define " << includeGuard << "\n"
+ << "QT_BEGIN_NAMESPACE\n"
+ << "namespace QtPrivate {\n";
+
+ stream << "inline void trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " tracepoint(" << provider.name << ", " << name << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline void do_trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " do_tracepoint(" << provider.name << ", " << name << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline bool trace_" << name << "_enabled()\n"
+ << "{\n"
+ << " return tracepoint_enabled(" << provider.name << ", " << name << ");\n"
+ << "}\n";
+
+ stream << "} // namespace QtPrivate\n"
+ << "QT_END_NAMESPACE\n"
+ << "#endif // " << includeGuard << "\n\n";
+}
+
+
+static void writeMetadataGenerators(QTextStream &stream)
+{
+ stream << R"CPP(
+template <typename T>
+inline QString integerToMetadata(const QString &name)
+{
+ QString ret;
+ if (!std::is_signed<T>().value)
+ ret += QLatin1Char('u');
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("int64_t ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("int32_t ");
+ else if (sizeof(T) == 2)
+ ret += QStringLiteral("int16_t ");
+ else if (sizeof(T) == 1)
+ ret += QStringLiteral("int8_t ");
+ ret += name + QLatin1Char(';');
+ return ret;
+}
+
+template <typename T>
+inline QString integerArrayToMetadata(const QString &size, const QString &name)
+{
+ QString ret;
+ if (!std::is_signed<T>().value)
+ ret += QLatin1Char('u');
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("int64_t ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("int32_t ");
+ else if (sizeof(T) == 2)
+ ret += QStringLiteral("int16_t ");
+ else if (sizeof(T) == 1)
+ ret += QStringLiteral("int8_t ");
+ ret += name + QLatin1Char('[') + size + QStringLiteral("];");
+ return ret;
+}
+
+template <typename T>
+inline QString floatToMetadata(const QString &name)
+{
+ QString ret;
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("double ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("float ");
+ ret += name + QLatin1Char(';');
+ return ret;
+}
+
+template <typename T>
+inline QString floatArrayToMetadata(const QString &size, const QString &name)
+{
+ QString ret;
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("double ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("float ");
+ ret += name + QLatin1Char('[') + size + QLatin1Char(']');
+ return ret + QLatin1Char(';');
+}
+
+inline QString pointerToMetadata(const QString &name)
+{
+ QString ret;
+ if (QT_POINTER_SIZE == 8)
+ ret += QStringLiteral("intptr64_t ");
+ else if (QT_POINTER_SIZE == 4)
+ ret += QStringLiteral("intptr32_t ");
+ ret += name + QLatin1Char(';');
+ return ret;
+}
+
+)CPP";
+}
+
+static void writeTracepoint(QTextStream &stream,
+ const Tracepoint &tracepoint, const QString &providerName)
+{
+ stream << "TRACEPOINT_EVENT(\n"
+ << " " << providerName << ",\n"
+ << " " << tracepoint.name << ",\n";
+
+ const auto checkUnknownArgs = [](const Tracepoint &tracepoint) {
+ for (auto &field : tracepoint.fields) {
+ if (field.backendType == Tracepoint::Field::Unknown)
+ return true;
+ }
+ return false;
+ };
+
+ const auto formatType = [](const QString &type) {
+ QString ret = type;
+ if (type.endsWith(QLatin1Char('*')) || type.endsWith(QLatin1Char('&')))
+ ret = type.left(type.length() - 1).simplified();
+ if (ret.startsWith(QStringLiteral("const")))
+ ret = ret.right(ret.length() - 6).simplified();
+ return typeToTypeName(ret);
+ };
+ QString eventSize;
+ bool variableSize = false;
+ const bool emptyMetadata = checkUnknownArgs(tracepoint) || tracepoint.args.size() == 0;
+ if (!emptyMetadata) {
+ for (int i = 0; i < tracepoint.args.size(); i++) {
+ auto &arg = tracepoint.args[i];
+ auto &field = tracepoint.fields[i];
+ if (i > 0) {
+ stream << " + QStringLiteral(\"\\n\\\n \") + ";
+ eventSize += QStringLiteral(" + ");
+ }
+ const bool array = field.arrayLen > 0;
+ switch (field.backendType) {
+ case Tracepoint::Field::Boolean: {
+ stream << "QStringLiteral(\"Boolean " << arg.name << ";\")";
+ eventSize += QStringLiteral("sizeof(bool)");
+ } break;
+ case Tracepoint::Field::Integer: {
+ if (array) {
+ stream << "integerArrayToMetadata<" << formatType(arg.type)
+ << ">(QStringLiteral(\"" << field.arrayLen << "\"), QStringLiteral(\""
+ << arg.name << "\"))";
+ } else {
+ stream << "integerToMetadata<" << formatType(arg.type) << ">(QStringLiteral(\""
+ << arg.name << "\"))";
+ }
+ eventSize += QStringLiteral("sizeof(") + formatType(arg.type) + QStringLiteral(")");
+ if (array)
+ eventSize += QStringLiteral(" * ") + QString::number(field.arrayLen);
+ } break;
+ case Tracepoint::Field::Pointer:
+ case Tracepoint::Field::IntegerHex: {
+ stream << "pointerToMetadata(QStringLiteral(\"" << formatType(arg.type) << "_"
+ << arg.name << "\"))";
+ eventSize += QStringLiteral("QT_POINTER_SIZE");
+ } break;
+ case Tracepoint::Field::Float: {
+ if (array) {
+ stream << "floatArrayToMetadata<" << formatType(arg.type)
+ << ">(QStringLiteral(\"" << field.arrayLen << "\"), QStringLiteral(\""
+ << arg.name << "\"))";
+ } else {
+ stream << "floatToMetadata<" << formatType(arg.type) << ">(QStringLiteral(\""
+ << arg.name << "\"))";
+ }
+ eventSize += QStringLiteral("sizeof(") + formatType(arg.type) + QStringLiteral(")");
+ if (array)
+ eventSize += QStringLiteral(" * ") + QString::number(field.arrayLen);
+ } break;
+ case Tracepoint::Field::QtUrl:
+ case Tracepoint::Field::QtString:
+ case Tracepoint::Field::String: {
+ stream << "QStringLiteral(\"string " << arg.name << ";\")";
+ eventSize += QStringLiteral("1");
+ variableSize = true;
+ } break;
+ case Tracepoint::Field::QtRect: {
+ stream << "QStringLiteral(\"int32_t QRect_" << arg.name << "_x;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_y;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("16");
+ } break;
+ case Tracepoint::Field::QtSize: {
+ stream << "QStringLiteral(\"int32_t QSize_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QSize_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("8");
+ } break;
+ case Tracepoint::Field::QtRectF: {
+ stream << "QStringLiteral(\"float QRectF_" << arg.name << "_x;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_y;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("16");
+ } break;
+ case Tracepoint::Field::QtSizeF: {
+ stream << "QStringLiteral(\"float QSizeF_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QSizeF_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("8");
+ } break;
+ case Tracepoint::Field::Unknown:
+ break;
+ case Tracepoint::Field::EnumeratedType: {
+ stream << "QStringLiteral(\"" << typeToTypeName(arg.type) << " " << arg.name << ";\")";
+ eventSize += QString::number(field.enumValueSize / 8);
+ variableSize = true;
+ } break;
+ case Tracepoint::Field::FlagType: {
+ stream << "QStringLiteral(\"uint8_t " << arg.name << "_length;\\n\\\n ";
+ stream << typeToTypeName(arg.type) << " " << arg.name << "[" << arg.name << "_length];\")";
+ eventSize += QStringLiteral("2");
+ variableSize = true;
+ } break;
+ case Tracepoint::Field::QtByteArray:
+ case Tracepoint::Field::Sequence:
+ panic("Unhandled type '%s %s", qPrintable(arg.type), qPrintable(arg.name));
+ break;
+ }
+ }
+ }
+
+ if (emptyMetadata)
+ stream << "{},\n";
+ else
+ stream << ",\n";
+ if (eventSize.length())
+ stream << eventSize << ", \n";
+ else
+ stream << "0, \n";
+ stream << (variableSize ? "true" : "false") << "\n";
+ stream << ")\n\n";
+}
+
+static void writeTracepoints(QTextStream &stream, const Provider &provider)
+{
+ for (const Tracepoint &t : provider.tracepoints) {
+ writeTracepoint(stream, t, provider.name);
+ writeWrapper(stream, t, provider);
+ }
+}
+
+static void writeEnums(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &e : provider.enumerations) {
+ QString name = e.name;
+ name.replace(QStringLiteral("::"), QStringLiteral("_"));
+ stream << "TRACEPOINT_METADATA(" << provider.name << ", " << name << ", \n";
+ stream << "QStringLiteral(\"typealias enum : integer { size = " << e.valueSize << "; } {\\n\\\n";
+
+ const auto values = e.values;
+ QList<int> handledValues;
+
+ for (const auto &v : values) {
+ if (handledValues.contains(v.value))
+ continue;
+ if (v.range) {
+ stream << v.name << " = " << v.value << " ... " << v.range << ", \\n\\\n";
+ } else {
+ const QString names = aggregateListValues(v.value, values);
+ stream << names << " = " << v.value << ", \\n\\\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << "} := " << name << ";\\n\\n\"));\n\n";
+ }
+ stream << "\n";
+}
+
+static void writeFlags(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &e : provider.flags) {
+ QString name = e.name;
+ name.replace(QStringLiteral("::"), QStringLiteral("_"));
+ stream << "TRACEPOINT_METADATA(" << provider.name << ", " << name << ", \n";
+ stream << "QStringLiteral(\"typealias enum : integer { size = 8; } {\\n\\\n";
+
+ const auto values = e.values;
+ QList<int> handledValues;
+
+ for (const auto &v : values) {
+ if (handledValues.contains(v.value))
+ continue;
+ const QString names = aggregateListValues(v.value, values);
+ stream << names << " = " << v.value << ", \\n\\\n";
+ handledValues.append(v.value);
+ }
+ stream << "} := " << name << ";\\n\\n\"));\n\n";
+ }
+ stream << "\n";
+}
+
+void writeCtf(QFile &file, const Provider &provider)
+{
+ QTextStream stream(&file);
+
+ const QString fileName = QFileInfo(file.fileName()).fileName();
+
+ writePrologue(stream, fileName, provider);
+ writeMetadataGenerators(stream);
+ writeEnums(stream, provider);
+ writeFlags(stream, provider);
+ writeTracepoints(stream, provider);
+ writeEpilogue(stream, fileName);
+}
diff --git a/src/tools/tracegen/ctf.h b/src/tools/tracegen/ctf.h
new file mode 100644
index 0000000000..113e30919f
--- /dev/null
+++ b/src/tools/tracegen/ctf.h
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef CTF_H
+#define CTF_H
+
+struct Provider;
+class QFile;
+
+void writeCtf(QFile &device, const Provider &p);
+
+#endif // CTF_H
diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp
index 8b0b7bf888..f54a7896ea 100644
--- a/src/tools/tracegen/etw.cpp
+++ b/src/tools/tracegen/etw.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "etw.h"
#include "provider.h"
@@ -47,15 +11,26 @@
#include <qtextstream.h>
#include <quuid.h>
+using namespace Qt::StringLiterals;
+
static inline QString providerVar(const QString &providerName)
{
- return providerName + QLatin1String("_provider");
+ return providerName + "_provider"_L1;
}
static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
{
const QString &name = field.name;
+ if (field.arrayLen > 0) {
+ for (int i = 0; i < field.arrayLen; i++) {
+ stream << "TraceLoggingValue(" << name << "[" << i << "], \"" << name << "[" << i << "]\")";
+ if (i + 1 < field.arrayLen)
+ stream << ",\n ";
+ }
+ return;
+ }
+
switch (field.backendType) {
case Tracepoint::Field::QtString:
stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
@@ -70,11 +45,17 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "TraceLoggingValue(" << name << ".toEncoded().constData(), \"" << name << "\")";
return;
case Tracepoint::Field::QtRect:
+ case Tracepoint::Field::QtRectF:
stream << "TraceLoggingValue(" << name << ".x(), \"x\"), "
<< "TraceLoggingValue(" << name << ".y(), \"y\"), "
<< "TraceLoggingValue(" << name << ".width(), \"width\"), "
<< "TraceLoggingValue(" << name << ".height(), \"height\")";
return;
+ case Tracepoint::Field::QtSize:
+ case Tracepoint::Field::QtSizeF:
+ stream << "TraceLoggingValue(" << name << ".width(), \"width\"), "
+ << "TraceLoggingValue(" << name << ".height(), \"height\")";
+ return;
case Tracepoint::Field::Pointer:
stream << "TraceLoggingPointer(" << name << ", \"" << name << "\")";
return;
@@ -85,6 +66,10 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>(" << name
<< "Str.utf16()), static_cast<ULONG>(" << name << "Str.size()), \"" << name << "\")";
return;
+ case Tracepoint::Field::EnumeratedType:
+ case Tracepoint::Field::FlagType:
+ stream << "TraceLoggingString(trace_convert_" << typeToTypeName(field.paramType) << "(" << name << ").toUtf8().constData(), \"" << name << "\")";
+ return;
default:
break;
}
@@ -119,6 +104,7 @@ static QString createGuid(const QUuid &uuid)
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
{
+ writeCommonPrologue(stream);
QUuid uuid = QUuid::createUuidV5(QUuid(), provider.name.toLocal8Bit());
const QString providerV = providerVar(provider.name);
@@ -146,7 +132,7 @@ static void writePrologue(QTextStream &stream, const QString &fileName, const Pr
stream << "\n";
if (!provider.prefixText.isEmpty())
- stream << provider.prefixText.join(QLatin1Char('\n')) << "\n\n";
+ stream << provider.prefixText.join(u'\n') << "\n\n";
stream << "#ifdef TRACEPOINT_DEFINE\n"
<< "/* " << guidString << " */\n"
@@ -177,14 +163,14 @@ static void writeEpilogue(QTextStream &stream, const QString &fileName)
<< "#include <private/qtrace_p.h>\n";
}
-static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
+static void writeWrapper(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint,
const QString &providerName)
{
const QString argList = formatFunctionSignature(tracepoint.args);
- const QString paramList = formatParameterList(tracepoint.args, ETW);
+ const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, ETW);
const QString &name = tracepoint.name;
const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
- const QString provider = providerVar(providerName);
+ const QString provar = providerVar(providerName);
stream << "\n";
@@ -199,7 +185,7 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
<< ");\n";
}
}
- stream << " TraceLoggingWrite(" << provider << ", \"" << name << "\"";
+ stream << " TraceLoggingWrite(" << provar << ", \"" << name << "\"";
for (const Tracepoint::Field &field : tracepoint.fields) {
stream << ",\n";
@@ -217,10 +203,56 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
stream << "inline bool trace_" << name << "_enabled()\n"
<< "{\n"
- << " return TraceLoggingProviderEnabled(" << provider << ", 0, 0);\n"
+ << " return TraceLoggingProviderEnabled(" << provar << ", 0, 0);\n"
<< "}\n";
}
+static void writeEnumConverter(QTextStream &stream, const TraceEnum &enumeration)
+{
+ stream << "inline QString trace_convert_" << typeToTypeName(enumeration.name) << "(" << enumeration.name << " val)\n";
+ stream << "{\n";
+ for (const auto &v : enumeration.values) {
+ if (v.range != 0) {
+ stream << " if (val >= " << v.value << " && val <= " << v.range << ")\n"
+ << " return QStringLiteral(\"" << v.name << " + \") + QString::number((int)val - " << v.value << ");\n";
+ }
+ }
+ stream << "\n QString ret;\n switch (val) {\n";
+
+ QList<int> handledValues;
+ for (const auto &v : enumeration.values) {
+ if (v.range == 0 && !handledValues.contains(v.value)) {
+ stream << " case " << v.value << ": ret = QStringLiteral(\""
+ << aggregateListValues(v.value, enumeration.values) << "\"); break;\n";
+ handledValues.append(v.value);
+ }
+ }
+
+ stream << " }\n return ret;\n}\n";
+}
+
+static void writeFlagConverter(QTextStream &stream, const TraceFlags &flag)
+{
+ stream << "inline QString trace_convert_" << typeToTypeName(flag.name) << "(" << flag.name << " val)\n";
+ stream << "{\n QString ret;\n";
+ for (const auto &v : flag.values) {
+ if (v.value == 0) {
+ stream << " if (val == 0)\n return QStringLiteral(\""
+ << aggregateListValues(v.value, flag.values) << "\");\n";
+ break;
+ }
+ }
+ QList<int> handledValues;
+ for (const auto &v : flag.values) {
+ if (v.value != 0 && !handledValues.contains(v.value)) {
+ stream << " if (val & " << (1 << (v.value - 1))
+ << ") { if (ret.length()) ret += QLatin1Char(\'|\'); ret += QStringLiteral(\"" << v.name << "\"); }\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << " return ret;\n}\n";
+}
+
static void writeTracepoints(QTextStream &stream, const Provider &provider)
{
if (provider.tracepoints.isEmpty())
@@ -233,8 +265,14 @@ static void writeTracepoints(QTextStream &stream, const Provider &provider)
<< "QT_BEGIN_NAMESPACE\n"
<< "namespace QtPrivate {\n";
+ for (const auto &enumeration : provider.enumerations)
+ writeEnumConverter(stream, enumeration);
+
+ for (const auto &flag : provider.flags)
+ writeFlagConverter(stream, flag);
+
for (const Tracepoint &t : provider.tracepoints)
- writeWrapper(stream, t, provider.name);
+ writeWrapper(stream, provider, t, provider.name);
stream << "} // namespace QtPrivate\n"
<< "QT_END_NAMESPACE\n"
diff --git a/src/tools/tracegen/etw.h b/src/tools/tracegen/etw.h
index 5fc9b57eaa..88508e2034 100644
--- a/src/tools/tracegen/etw.h
+++ b/src/tools/tracegen/etw.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef ETW_H
#define ETW_H
diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp
index 8ffc088fed..0ea5848493 100644
--- a/src/tools/tracegen/helpers.cpp
+++ b/src/tools/tracegen/helpers.cpp
@@ -1,52 +1,33 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "helpers.h"
#include <qdebug.h>
+using namespace Qt::StringLiterals;
+
+void writeCommonPrologue(QTextStream &stream)
+{
+ stream << R"CPP(
+#ifndef Q_TRACEPOINT
+#error "Q_TRACEPOINT not set for the module, Q_TRACE not enabled."
+#endif
+)CPP";
+}
+
+QString typeToTypeName(const QString &name)
+{
+ QString ret = name;
+ return ret.replace(QStringLiteral("::"), QStringLiteral("_"));
+}
+
QString includeGuard(const QString &filename)
{
QString guard = filename.toUpper();
for (int i = 0; i < guard.size(); ++i) {
if (!guard.at(i).isLetterOrNumber())
- guard[i] = QLatin1Char('_');
+ guard[i] = u'_';
}
return guard;
@@ -60,7 +41,7 @@ static QString joinArguments(const QList<Tracepoint::Argument> &args, T joinFunc
for (const Tracepoint::Argument &arg : args) {
if (!first)
- ret += QLatin1String(", ");
+ ret += ", "_L1;
ret += joinFunction(arg);
@@ -77,14 +58,56 @@ QString formatFunctionSignature(const QList<Tracepoint::Argument> &args)
});
}
-QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type)
+QString formatParameterList(const Provider &provider, const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type)
{
if (type == LTTNG) {
QString ret;
- for (const Tracepoint::Argument &arg : args)
- ret += QLatin1String(", ") + arg.name;
+ for (int i = 0; i < args.size(); i++) {
+ const Tracepoint::Argument &arg = args[i];
+ const Tracepoint::Field &field = fields[i];
+ if (field.backendType == Tracepoint::Field::FlagType)
+ ret += ", trace_convert_"_L1 + typeToTypeName(arg.type) + "("_L1 + arg.name + ")"_L1;
+ else
+ ret += ", "_L1 + arg.name;
+ }
+ return ret;
+ }
+
+ auto findEnumeration = [](const QList<TraceEnum> &enums, const QString &name) {
+ for (const auto &e : enums) {
+ if (e.name == name)
+ return e;
+ }
+ return TraceEnum();
+ };
+
+ if (type == CTF) {
+ QString ret;
+ for (int i = 0; i < args.size(); i++) {
+ const Tracepoint::Argument &arg = args[i];
+ const Tracepoint::Field &field = fields[i];
+ if (arg.arrayLen > 1) {
+ ret += ", trace::toByteArrayFromArray("_L1 + arg.name + ", "_L1 + QString::number(arg.arrayLen) + ") "_L1;
+ } else if (field.backendType == Tracepoint::Field::EnumeratedType) {
+ const TraceEnum &e = findEnumeration(provider.enumerations, arg.type);
+ QString integerType;
+ if (e.valueSize == 8)
+ integerType = QStringLiteral("quint8");
+ else if (e.valueSize == 16)
+ integerType = QStringLiteral("quint16");
+ else
+ integerType = QStringLiteral("quint32");
+ ret += ", trace::toByteArrayFromEnum<"_L1 + integerType + ">("_L1 + arg.name + ")"_L1;
+ } else if (field.backendType == Tracepoint::Field::FlagType) {
+ ret += ", trace::toByteArrayFromFlags("_L1 + arg.name + ")"_L1;
+ } else if (field.backendType == Tracepoint::Field::String) {
+ ret += ", trace::toByteArrayFromCString("_L1 + arg.name + ")"_L1;
+ } else {
+ ret += ", "_L1 + arg.name;
+ }
+ }
return ret;
}
diff --git a/src/tools/tracegen/helpers.h b/src/tools/tracegen/helpers.h
index 8acf6e2292..ea6db016a6 100644
--- a/src/tools/tracegen/helpers.h
+++ b/src/tools/tracegen/helpers.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef HELPERS_H
#define HELPERS_H
@@ -44,14 +8,30 @@
#include <qlist.h>
#include <qstring.h>
+#include <qtextstream.h>
enum ParamType {
LTTNG,
- ETW
+ ETW,
+ CTF
};
+QString typeToTypeName(const QString &type);
QString includeGuard(const QString &filename);
QString formatFunctionSignature(const QList<Tracepoint::Argument> &args);
-QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type);
+QString formatParameterList(const Provider &provider, const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type);
+
+void writeCommonPrologue(QTextStream &stream);
+
+template <typename T>
+static QString aggregateListValues(int value, const QList<T> &list)
+{
+ QStringList values;
+ for (const T &l : list) {
+ if (l.value == value)
+ values << l.name;
+ }
+ return values.join(QLatin1Char('_'));
+}
#endif // HELPERS_H
diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp
index 9a8dfc9f4a..9711570874 100644
--- a/src/tools/tracegen/lttng.cpp
+++ b/src/tools/tracegen/lttng.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "lttng.h"
#include "provider.h"
@@ -48,23 +12,37 @@
#include <qtextstream.h>
#include <qdebug.h>
-static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
+static void writeCtfMacro(QTextStream &stream, const Provider &provider, const Tracepoint::Field &field)
{
const QString &paramType = field.paramType;
const QString &name = field.name;
const QString &seqLen = field.seqLen;
const int arrayLen = field.arrayLen;
- switch (field.backendType) {
- case Tracepoint::Field::Array:
- stream << "ctf_array(" <<paramType << ", "
- << name << ", " << name << ", " << arrayLen << ")";
+ if (arrayLen > 0) {
+ if (paramType == QStringLiteral("double") || paramType == QStringLiteral("float")) {
+ const char *newline = nullptr;
+ for (int i = 0; i < arrayLen; i++) {
+ stream << newline;
+ stream << "ctf_float(" <<paramType << ", " << name << "_" << QString::number(i) << ", "
+ << name << "[" << QString::number(i) << "]" << ")";
+ newline = "\n ";
+ }
+
+ } else {
+ stream << "ctf_array(" <<paramType << ", "
+ << name << ", " << name << ", " << arrayLen << ")";
+ }
return;
+ }
+
+ switch (field.backendType) {
case Tracepoint::Field::Sequence:
stream << "ctf_sequence(" << paramType
<< ", " << name << ", " << name
<< ", unsigned int, " << seqLen << ")";
return;
+ case Tracepoint::Field::Boolean:
case Tracepoint::Field::Integer:
stream << "ctf_integer(" << paramType << ", " << name << ", " << name << ")";
return;
@@ -79,33 +57,51 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "ctf_string(" << name << ", " << name << ")";
return;
case Tracepoint::Field::QtString:
- stream << "ctf_sequence(const ushort, " << name << ", "
- << name << ".utf16(), unsigned int, " << name << ".size())";
+ stream << "ctf_string(" << name << ", " << name << ".toUtf8().constData())";
return;
case Tracepoint::Field::QtByteArray:
stream << "ctf_sequence(const char, " << name << ", "
<< name << ".constData(), unsigned int, " << name << ".size())";
return;
case Tracepoint::Field::QtUrl:
- stream << "ctf_sequence(const char, " << name << ", "
- << name << ".toEncoded().constData(), unsigned int, "
- << name << ".toEncoded().size())";
+ stream << "ctf_string(" << name << ", " << name << ".toString().toUtf8().constData())";
return;
case Tracepoint::Field::QtRect:
- stream << "ctf_integer(int, x, " << name << ".x()) "
- << "ctf_integer(int, y, " << name << ".y()) "
- << "ctf_integer(int, width, " << name << ".width()) "
- << "ctf_integer(int, height, " << name << ".height()) ";
+ stream << "ctf_integer(int, QRect_" << name << "_x, " << name << ".x()) "
+ << "ctf_integer(int, QRect_" << name << "_y, " << name << ".y()) "
+ << "ctf_integer(int, QRect_" << name << "_width, " << name << ".width()) "
+ << "ctf_integer(int, QRect_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::QtSizeF:
+ stream << "ctf_float(double, QSizeF_" << name << "_width, " << name << ".width()) "
+ << "ctf_float(double, QSizeF_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::QtRectF:
+ stream << "ctf_float(double, QRectF_" << name << "_x, " << name << ".x()) "
+ << "ctf_float(double, QRectF_" << name << "_y, " << name << ".y()) "
+ << "ctf_float(double, QRectF_" << name << "_width, " << name << ".width()) "
+ << "ctf_float(double, QRectF_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::QtSize:
+ stream << "ctf_integer(int, QSize_" << name << "_width, " << name << ".width()) "
+ << "ctf_integer(int, QSize_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::EnumeratedType:
+ stream << "ctf_enum(" << provider.name << ", " << typeToTypeName(paramType) << ", int, " << name << ", " << name << ") ";
+ return;
+ case Tracepoint::Field::FlagType:
+ stream << "ctf_sequence(const char , " << name << ", "
+ << name << ".constData(), unsigned int, " << name << ".size())";
return;
case Tracepoint::Field::Unknown:
- justified_worry("Cannot deduce CTF type for '%s %s'", qPrintable(paramType),
- qPrintable(name));
+ panic("Cannot deduce CTF type for '%s %s", qPrintable(paramType), qPrintable(name));
break;
}
}
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
{
+ writeCommonPrologue(stream);
const QString guard = includeGuard(fileName);
stream << "#undef TRACEPOINT_PROVIDER\n";
@@ -117,7 +113,7 @@ static void writePrologue(QTextStream &stream, const QString &fileName, const Pr
stream << qtHeaders();
stream << "\n";
if (!provider.prefixText.isEmpty())
- stream << provider.prefixText.join(QLatin1Char('\n')) << "\n\n";
+ stream << provider.prefixText.join(u'\n') << "\n\n";
stream << "#endif\n\n";
/* the first guard is the usual one, the second is required
@@ -147,12 +143,12 @@ static void writeEpilogue(QTextStream &stream, const QString &fileName)
}
static void writeWrapper(QTextStream &stream,
- const Tracepoint &tracepoint, const QString &providerName)
+ const Tracepoint &tracepoint, const Provider &provider)
{
const QString argList = formatFunctionSignature(tracepoint.args);
- const QString paramList = formatParameterList(tracepoint.args, LTTNG);
+ const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, LTTNG);
const QString &name = tracepoint.name;
- const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
+ const QString includeGuard = QStringLiteral("TP_%1_%2").arg(provider.name).arg(name).toUpper();
/* prevents the redefinion of the inline wrapper functions
* once LTTNG recursively includes this header file
@@ -165,17 +161,17 @@ static void writeWrapper(QTextStream &stream,
stream << "inline void trace_" << name << "(" << argList << ")\n"
<< "{\n"
- << " tracepoint(" << providerName << ", " << name << paramList << ");\n"
+ << " tracepoint(" << provider.name << ", " << name << paramList << ");\n"
<< "}\n";
stream << "inline void do_trace_" << name << "(" << argList << ")\n"
<< "{\n"
- << " do_tracepoint(" << providerName << ", " << name << paramList << ");\n"
+ << " do_tracepoint(" << provider.name << ", " << name << paramList << ");\n"
<< "}\n";
stream << "inline bool trace_" << name << "_enabled()\n"
<< "{\n"
- << " return tracepoint_enabled(" << providerName << ", " << name << ");\n"
+ << " return tracepoint_enabled(" << provider.name << ", " << name << ");\n"
<< "}\n";
stream << "} // namespace QtPrivate\n"
@@ -183,7 +179,7 @@ static void writeWrapper(QTextStream &stream,
<< "#endif // " << includeGuard << "\n\n";
}
-static void writeTracepoint(QTextStream &stream,
+static void writeTracepoint(QTextStream &stream, const Provider &provider,
const Tracepoint &tracepoint, const QString &providerName)
{
stream << "TRACEPOINT_EVENT(\n"
@@ -193,8 +189,13 @@ static void writeTracepoint(QTextStream &stream,
const char *comma = nullptr;
- for (const Tracepoint::Argument &arg : tracepoint.args) {
- stream << comma << arg.type << ", " << arg.name;
+ for (int i = 0; i < tracepoint.args.size(); i++) {
+ const auto &arg = tracepoint.args[i];
+ const auto &field = tracepoint.fields[i];
+ if (field.backendType == Tracepoint::Field::FlagType)
+ stream << comma << "QByteArray, " << arg.name;
+ else
+ stream << comma << arg.type << ", " << arg.name;
comma = ", ";
}
@@ -205,18 +206,82 @@ static void writeTracepoint(QTextStream &stream,
for (const Tracepoint::Field &f : tracepoint.fields) {
stream << newline;
- writeCtfMacro(stream, f);
+ writeCtfMacro(stream, provider, f);
newline = "\n ";
}
stream << ")\n)\n\n";
}
+static void writeEnums(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &e : provider.enumerations) {
+ stream << "TRACEPOINT_ENUM(\n"
+ << " " << provider.name << ",\n"
+ << " " << typeToTypeName(e.name) << ",\n"
+ << " TP_ENUM_VALUES(\n";
+ QList<int> handledValues;
+ for (const auto &v : e.values) {
+ if (v.range > 0) {
+ stream << " ctf_enum_range(\"" << v.name << "\", " << v.value << ", " << v.range << ")\n";
+ } else if (!handledValues.contains(v.value)) {
+ stream << " ctf_enum_value(\"" << aggregateListValues(v.value, e.values) << "\", " << v.value << ")\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << " )\n)\n\n";
+ }
+}
+
+static void writeFlags(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &f : provider.flags) {
+ stream << "TRACEPOINT_ENUM(\n"
+ << " " << provider.name << ",\n"
+ << " " << typeToTypeName(f.name) << ",\n"
+ << " TP_ENUM_VALUES(\n";
+ QList<int> handledValues;
+ for (const auto &v : f.values) {
+ if (!handledValues.contains(v.value)) {
+ stream << " ctf_enum_value(\"" << aggregateListValues(v.value, f.values) << "\", " << v.value << ")\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << " )\n)\n\n";
+ }
+
+ // converters
+ const QString includeGuard = QStringLiteral("TP_%1_CONVERTERS").arg(provider.name).toUpper();
+ stream << "\n"
+ << "#ifndef " << includeGuard << "\n"
+ << "#define " << includeGuard << "\n";
+ stream << "QT_BEGIN_NAMESPACE\n";
+ stream << "namespace QtPrivate {\n";
+ for (const auto &f : provider.flags) {
+ stream << "inline QByteArray trace_convert_" << typeToTypeName(f.name) << "(" << f.name << " val)\n";
+ stream << "{\n";
+ stream << " QByteArray ret;\n";
+ stream << " if (val == 0) { ret.append((char)0); return ret; }\n";
+
+ for (const auto &v : f.values) {
+ if (!v.value)
+ continue;
+ stream << " if (val & " << (1 << (v.value - 1)) << ") { ret.append((char)" << v.value << "); };\n";
+ }
+ stream << " return ret;\n";
+ stream << "}\n";
+
+ }
+ stream << "} // namespace QtPrivate\n"
+ << "QT_END_NAMESPACE\n\n"
+ << "#endif // " << includeGuard << "\n\n";
+}
+
static void writeTracepoints(QTextStream &stream, const Provider &provider)
{
for (const Tracepoint &t : provider.tracepoints) {
- writeTracepoint(stream, t, provider.name);
- writeWrapper(stream, t, provider.name);
+ writeTracepoint(stream, provider, t, provider.name);
+ writeWrapper(stream, t, provider);
}
}
@@ -227,6 +292,9 @@ void writeLttng(QFile &file, const Provider &provider)
const QString fileName = QFileInfo(file.fileName()).fileName();
writePrologue(stream, fileName, provider);
+ writeEnums(stream, provider);
+ writeFlags(stream, provider);
writeTracepoints(stream, provider);
writeEpilogue(stream, fileName);
}
+
diff --git a/src/tools/tracegen/lttng.h b/src/tools/tracegen/lttng.h
index 0307b375bc..c36c70a1d4 100644
--- a/src/tools/tracegen/lttng.h
+++ b/src/tools/tracegen/lttng.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef LTTNG_H
#define LTTNG_H
diff --git a/src/tools/tracegen/panic.cpp b/src/tools/tracegen/panic.cpp
index ac95b2e9e8..fa4e6b3ee3 100644
--- a/src/tools/tracegen/panic.cpp
+++ b/src/tools/tracegen/panic.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "panic.h"
@@ -57,16 +21,3 @@ void panic(const char *fmt, ...)
exit(EXIT_FAILURE);
}
-
-void justified_worry(const char *fmt, ...)
-{
- va_list ap;
-
- fprintf(stderr, "tracegen: warning: ");
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fputc('\n', stderr);
-}
diff --git a/src/tools/tracegen/panic.h b/src/tools/tracegen/panic.h
index 58e56c0116..ee635a8aeb 100644
--- a/src/tools/tracegen/panic.h
+++ b/src/tools/tracegen/panic.h
@@ -1,46 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PANIC_H
#define PANIC_H
void panic(const char *fmt, ...);
-void justified_worry(const char *fmt, ...);
#endif // PANIC_H
diff --git a/src/tools/tracegen/provider.cpp b/src/tools/tracegen/provider.cpp
index 7984fa12a7..bdd669c9cd 100644
--- a/src/tools/tracegen/provider.cpp
+++ b/src/tools/tracegen/provider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "provider.h"
#include "panic.h"
@@ -45,6 +9,9 @@
#include <qtextstream.h>
#include <qregularexpression.h>
#include <qstring.h>
+#include <qtpreprocessorsupport.h>
+
+using namespace Qt::StringLiterals;
#ifdef TRACEGEN_DEBUG
#include <qdebug.h>
@@ -129,89 +96,115 @@ static QString removeBraces(QString type)
return type.remove(rx);
}
-static Tracepoint::Field::BackendType backendType(QString rawType)
+#define TYPEDATA_ENTRY(type, backendType) \
+{ QT_STRINGIFY(type), backendType }
+
+static Tracepoint::Field::Type backendType(QString rawType)
{
- static const struct {
+ static const struct TypeData {
const char *type;
- Tracepoint::Field::BackendType backendType;
+ Tracepoint::Field::Type backendType;
} typeTable[] = {
- { "bool", Tracepoint::Field::Integer },
- { "short_int", Tracepoint::Field::Integer },
- { "signed_short", Tracepoint::Field::Integer },
- { "signed_short_int", Tracepoint::Field::Integer },
- { "unsigned_short", Tracepoint::Field::Integer },
- { "unsigned_short_int", Tracepoint::Field::Integer },
- { "int", Tracepoint::Field::Integer },
- { "signed", Tracepoint::Field::Integer },
- { "signed_int", Tracepoint::Field::Integer },
- { "unsigned", Tracepoint::Field::Integer },
- { "unsigned_int", Tracepoint::Field::Integer },
- { "long", Tracepoint::Field::Integer },
- { "long_int", Tracepoint::Field::Integer },
- { "signed_long", Tracepoint::Field::Integer },
- { "signed_long_int", Tracepoint::Field::Integer },
- { "unsigned_long", Tracepoint::Field::Integer },
- { "unsigned_long_int", Tracepoint::Field::Integer },
- { "long_long", Tracepoint::Field::Integer },
- { "long_long_int", Tracepoint::Field::Integer },
- { "signed_long_long", Tracepoint::Field::Integer },
- { "signed_long_long_int", Tracepoint::Field::Integer },
- { "unsigned_long_long", Tracepoint::Field::Integer },
- { "char", Tracepoint::Field::Integer },
- { "intptr_t", Tracepoint::Field::IntegerHex },
- { "uintptr_t", Tracepoint::Field::IntegerHex },
- { "std::intptr_t", Tracepoint::Field::IntegerHex },
- { "std::uintptr_t", Tracepoint::Field::IntegerHex },
- { "float", Tracepoint::Field::Float },
- { "double", Tracepoint::Field::Float },
- { "long_double", Tracepoint::Field::Float },
- { "QString", Tracepoint::Field::QtString },
- { "QByteArray", Tracepoint::Field::QtByteArray },
- { "QUrl", Tracepoint::Field::QtUrl },
- { "QRect", Tracepoint::Field::QtRect }
+ TYPEDATA_ENTRY(short_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_short, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_short_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_short, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_short_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_long_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(bool, Tracepoint::Field::Boolean),
+ TYPEDATA_ENTRY(int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(qint64, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(char, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(intptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(uintptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(std::intptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(std::uintptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(float, Tracepoint::Field::Float),
+ TYPEDATA_ENTRY(double, Tracepoint::Field::Float),
+ TYPEDATA_ENTRY(long double, Tracepoint::Field::Float),
+ TYPEDATA_ENTRY(QString, Tracepoint::Field::QtString),
+ TYPEDATA_ENTRY(QByteArray, Tracepoint::Field::QtByteArray),
+ TYPEDATA_ENTRY(QUrl, Tracepoint::Field::QtUrl),
+ TYPEDATA_ENTRY(QRect, Tracepoint::Field::QtRect),
+ TYPEDATA_ENTRY(QSize, Tracepoint::Field::QtSize),
+ TYPEDATA_ENTRY(QRectF, Tracepoint::Field::QtRectF),
+ TYPEDATA_ENTRY(QSizeF, Tracepoint::Field::QtSizeF)
};
auto backendType = [](const QString &rawType) {
static const size_t tableSize = sizeof (typeTable) / sizeof (typeTable[0]);
for (size_t i = 0; i < tableSize; ++i) {
- if (rawType == QLatin1String(typeTable[i].type))
- return typeTable[i].backendType;
+ if (rawType == QLatin1StringView(typeTable[i].type))
+ return typeTable[i];
}
- return Tracepoint::Field::Unknown;
+ TypeData unknown = { nullptr, Tracepoint::Field::Unknown };
+ return unknown;
};
- if (arrayLength(rawType) > 0)
- return Tracepoint::Field::Array;
+ int arrayLen = arrayLength(rawType);
+ if (arrayLen > 0)
+ rawType = removeBraces(rawType);
if (!sequenceLength(rawType).isNull())
return Tracepoint::Field::Sequence;
static const QRegularExpression constMatch(QStringLiteral("\\bconst\\b"));
rawType.remove(constMatch);
- rawType.remove(QLatin1Char('&'));
+ rawType.remove(u'&');
static const QRegularExpression ptrMatch(QStringLiteral("\\s*\\*\\s*"));
rawType.replace(ptrMatch, QStringLiteral("_ptr"));
rawType = rawType.trimmed();
rawType.replace(QStringLiteral(" "), QStringLiteral("_"));
- if (rawType == QLatin1String("char_ptr"))
+ if (rawType == "char_ptr"_L1)
return Tracepoint::Field::String;
- if (rawType.endsWith(QLatin1String("_ptr")))
+ if (rawType.endsWith("_ptr"_L1))
return Tracepoint::Field::Pointer;
- return backendType(rawType);
+ TypeData d = backendType(rawType);
+ return d.backendType;
}
-static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
+static Tracepoint parseTracepoint(const Provider &provider, const QString &name, const QStringList &args,
const QString &fileName, const int lineNumber)
{
Tracepoint t;
t.name = name;
+ auto findEnumeration = [](const QList<TraceEnum> &enums, const QString &name) {
+ for (const auto &e : enums) {
+ if (e.name == name)
+ return e;
+ }
+ return TraceEnum();
+ };
+ auto findFlags = [](const QList<TraceFlags> &flags, const QString &name) {
+ for (const auto &f : flags) {
+ if (f.name == name)
+ return f;
+ }
+ return TraceFlags();
+ };
+
+
if (args.isEmpty())
return t;
@@ -247,14 +240,23 @@ static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
t.args << std::move(a);
- Tracepoint::Field f;
- f.backendType = backendType(type);
- f.paramType = removeBraces(type);
- f.name = name;
- f.arrayLen = arrayLen;
- f.seqLen = sequenceLength(type);
+ Tracepoint::Field field;
+ const TraceEnum &e = findEnumeration(provider.enumerations, type);
+ const TraceFlags &f = findFlags(provider.flags, type);
+ if (!e.name.isEmpty()) {
+ field.backendType = Tracepoint::Field::EnumeratedType;
+ field.enumValueSize = e.valueSize;
+ } else if (!f.name.isEmpty()) {
+ field.backendType = Tracepoint::Field::FlagType;
+ } else {
+ field.backendType = backendType(type);
+ }
+ field.paramType = removeBraces(type);
+ field.name = name;
+ field.arrayLen = arrayLen;
+ field.seqLen = sequenceLength(type);
- t.fields << std::move(f);
+ t.fields << std::move(field);
++i;
}
@@ -262,6 +264,31 @@ static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
return t;
}
+static int minumumValueSize(int min, int max)
+{
+ if (min < 0) {
+ if (min >= std::numeric_limits<char>::min() && max <= std::numeric_limits<char>::max())
+ return 8;
+ if (min >= std::numeric_limits<short>::min() && max <= std::numeric_limits<short>::max())
+ return 16;
+ return 32;
+ }
+ if (max <= std::numeric_limits<unsigned char>::max())
+ return 8;
+ if (max <= std::numeric_limits<unsigned short>::max())
+ return 16;
+ return 32;
+}
+
+static bool isPow2OrZero(quint32 value)
+{
+ return (value & (value - 1)) == 0;
+}
+
+static quint32 pow2Log2(quint32 v) {
+ return 32 - qCountLeadingZeroBits(v);
+}
+
Provider parseProvider(const QString &filename)
{
QFile f(filename);
@@ -272,35 +299,140 @@ Provider parseProvider(const QString &filename)
QTextStream s(&f);
static const QRegularExpression tracedef(QStringLiteral("^([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)$"));
+ static const QRegularExpression enumenddef(QStringLiteral("^} ?([A-Za-z][A-Za-z0-9_:]*);"));
+ static const QRegularExpression enumdef(QStringLiteral("^([A-Za-z][A-Za-z0-9_]*)( *= *([xabcdef0-9]*))?"));
+ static const QRegularExpression rangedef(QStringLiteral("^RANGE\\(([A-Za-z][A-Za-z0-9_]*) ?, ?([0-9]*) ?... ?([0-9]*) ?\\)"));
Provider provider;
provider.name = QFileInfo(filename).baseName();
bool parsingPrefixText = false;
+ bool parsingEnum = false;
+ bool parsingFlags = false;
+ TraceEnum currentEnum;
+ TraceFlags currentFlags;
+ int currentEnumValue = 0;
+ int minEnumValue = std::numeric_limits<int>::max();
+ int maxEnumValue = std::numeric_limits<int>::min();
for (int lineNumber = 1; !s.atEnd(); ++lineNumber) {
QString line = s.readLine().trimmed();
- if (line == QLatin1String("{")) {
+ if (line == "{"_L1) {
parsingPrefixText = true;
continue;
- } else if (parsingPrefixText && line == QLatin1String("}")) {
+ } else if (parsingPrefixText && line == "}"_L1) {
parsingPrefixText = false;
continue;
} else if (parsingPrefixText) {
provider.prefixText.append(line);
continue;
+ } else if (line == "ENUM {"_L1) {
+ parsingEnum = true;
+ continue;
+ } else if (line == "FLAGS {"_L1) {
+ parsingFlags = true;
+ continue;
+ } else if (line.startsWith("}"_L1) && (parsingEnum || parsingFlags)) {
+ auto match = enumenddef.match(line);
+ if (match.hasMatch()) {
+ if (parsingEnum) {
+ currentEnum.name = match.captured(1);
+ currentEnum.valueSize = minumumValueSize(minEnumValue, maxEnumValue);
+ provider.enumerations.push_back(currentEnum);
+ currentEnum = TraceEnum();
+ parsingEnum = false;
+ } else {
+ currentFlags.name = match.captured(1);
+ provider.flags.push_back(currentFlags);
+ currentFlags = TraceFlags();
+ parsingFlags = false;
+ }
+
+ minEnumValue = std::numeric_limits<int>::max();
+ maxEnumValue = std::numeric_limits<int>::min();
+ } else {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' end of enum/flags does not match",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+
+ continue;
}
- if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
+ if (line.isEmpty() || line.startsWith(u'#'))
continue;
+ if (parsingEnum || parsingFlags) {
+ auto m = enumdef.match(line);
+ if (parsingEnum && line.startsWith(QStringLiteral("RANGE"))) {
+ auto m = rangedef.match(line);
+ if (m.hasMatch()) {
+ TraceEnum::EnumValue value;
+ value.name = m.captured(1);
+ value.value = m.captured(2).toInt();
+ value.range = m.captured(3).toInt();
+ currentEnumValue = value.range + 1;
+ currentEnum.values.push_back(value);
+ maxEnumValue = qMax(maxEnumValue, value.range);
+ minEnumValue = qMin(minEnumValue, value.value);
+ }
+ } else if (m.hasMatch()) {
+ if (m.hasCaptured(3)) {
+ if (parsingEnum) {
+ TraceEnum::EnumValue value;
+ value.name = m.captured(1);
+ value.value = m.captured(3).toInt();
+ value.range = 0;
+ currentEnumValue = value.value + 1;
+ currentEnum.values.push_back(value);
+ maxEnumValue = qMax(maxEnumValue, value.value);
+ minEnumValue = qMin(minEnumValue, value.value);
+ } else {
+ TraceFlags::FlagValue value;
+ value.name = m.captured(1);
+ if (m.captured(3).startsWith(QStringLiteral("0x")))
+ value.value = m.captured(3).toInt(nullptr, 16);
+ else
+ value.value = m.captured(3).toInt();
+ if (!isPow2OrZero(value.value)) {
+ printf("Warning: '%s' line %d:\n"
+ " '%s' flag value is not power of two.\n",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ } else {
+ value.value = pow2Log2(value.value);
+ currentFlags.values.push_back(value);
+ }
+ }
+ } else {
+ maxEnumValue = qMax(maxEnumValue, currentEnumValue);
+ minEnumValue = qMin(minEnumValue, currentEnumValue);
+ if (parsingEnum) {
+ currentEnum.values.push_back({m.captured(0), currentEnumValue++, 0});
+ } else {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' flags value not set",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+ }
+ } else {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' enum/flags does not match",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+ continue;
+ }
+
auto match = tracedef.match(line);
if (match.hasMatch()) {
const QString name = match.captured(1);
const QString argsString = match.captured(2);
- const QStringList args = argsString.split(QLatin1Char(','), Qt::SkipEmptyParts);
+ const QStringList args = argsString.split(u',', Qt::SkipEmptyParts);
- provider.tracepoints << parseTracepoint(name, args, filename, lineNumber);
+ provider.tracepoints << parseTracepoint(provider, name, args, filename, lineNumber);
} else {
panic("Syntax error while processing '%s' line %d:\n"
" '%s' does not look like a tracepoint definition",
diff --git a/src/tools/tracegen/provider.h b/src/tools/tracegen/provider.h
index 99b10b13f1..e5e99b868e 100644
--- a/src/tools/tracegen/provider.h
+++ b/src/tools/tracegen/provider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PROVIDER_H
#define PROVIDER_H
@@ -56,9 +20,9 @@ struct Tracepoint
struct Field
{
- enum BackendType {
- Array,
+ enum Type {
Sequence,
+ Boolean,
Integer,
IntegerHex,
Float,
@@ -68,13 +32,18 @@ struct Tracepoint
QtByteArray,
QtUrl,
QtRect,
+ QtSize,
+ QtRectF,
+ QtSizeF,
+ EnumeratedType,
+ FlagType,
Unknown
};
-
- BackendType backendType;
+ Type backendType;
QString paramType;
QString name;
int arrayLen;
+ int enumValueSize;
QString seqLen;
};
@@ -83,17 +52,41 @@ struct Tracepoint
QList<Field> fields;
};
+struct TraceEnum {
+ QString name;
+ struct EnumValue {
+ QString name;
+ int value;
+ int range;
+ };
+ QList<EnumValue> values;
+ int valueSize;
+};
+
+struct TraceFlags {
+ QString name;
+ struct FlagValue {
+ QString name;
+ int value;
+ };
+ QList<FlagValue> values;
+};
+
+Q_DECLARE_TYPEINFO(TraceEnum, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(TraceFlags, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint, Q_RELOCATABLE_TYPE);
+
struct Provider
{
QString name;
QList<Tracepoint> tracepoints;
QStringList prefixText;
+ QList<TraceEnum> enumerations;
+ QList<TraceFlags> flags;
};
Provider parseProvider(const QString &filename);
-Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(Tracepoint, Q_RELOCATABLE_TYPE);
-
#endif // PROVIDER_H
diff --git a/src/tools/tracegen/qtheaders.cpp b/src/tools/tracegen/qtheaders.cpp
index eec3488a6d..237c22b237 100644
--- a/src/tools/tracegen/qtheaders.cpp
+++ b/src/tools/tracegen/qtheaders.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qtheaders.h"
diff --git a/src/tools/tracegen/qtheaders.h b/src/tools/tracegen/qtheaders.h
index b80d374ca8..86405c9479 100644
--- a/src/tools/tracegen/qtheaders.h
+++ b/src/tools/tracegen/qtheaders.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QTHEADERS_H
#define QTHEADERS_H
diff --git a/src/tools/tracegen/tracegen.cpp b/src/tools/tracegen/tracegen.cpp
index 978fe406d0..776d81675d 100644
--- a/src/tools/tracegen/tracegen.cpp
+++ b/src/tools/tracegen/tracegen.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "provider.h"
+#include "ctf.h"
#include "lttng.h"
#include "etw.h"
#include "panic.h"
@@ -48,12 +13,13 @@
enum class Target
{
LTTNG,
- ETW
+ ETW,
+ CTF,
};
static inline void usage(int status)
{
- printf("Usage: tracegen <lttng|etw> <input file> <output file>\n");
+ printf("Usage: tracegen <lttng|etw|ctf> <input file> <output file>\n");
exit(status);
}
@@ -70,13 +36,15 @@ static void parseArgs(int argc, char *argv[], Target *target, QString *inFile, Q
*target = Target::LTTNG;
} else if (qstrcmp(targetString, "etw") == 0) {
*target = Target::ETW;
+ } else if (qstrcmp(targetString, "ctf") == 0) {
+ *target = Target::CTF;
} else {
fprintf(stderr, "Invalid target: %s\n", targetString);
usage(EXIT_FAILURE);
}
- *inFile = QLatin1String(argv[2]);
- *outFile = QLatin1String(argv[3]);
+ *inFile = QLatin1StringView(argv[2]);
+ *outFile = QLatin1StringView(argv[3]);
}
int main(int argc, char *argv[])
@@ -97,6 +65,9 @@ int main(int argc, char *argv[])
}
switch (target) {
+ case Target::CTF:
+ writeCtf(out, p);
+ break;
case Target::LTTNG:
writeLttng(out, p);
break;
diff --git a/src/tools/tracepointgen/CMakeLists.txt b/src/tools/tracepointgen/CMakeLists.txt
new file mode 100644
index 0000000000..2f473d376a
--- /dev/null
+++ b/src/tools/tracepointgen/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## tracepointgen Tool:
+#####################################################################
+
+qt_get_tool_target_name(target_name tracepointgen)
+qt_internal_add_tool(${target_name}
+ CORE_LIBRARY Bootstrap
+ INSTALL_DIR "${INSTALL_LIBEXECDIR}"
+ TOOLS_TARGET Core
+ SOURCES
+ tracepointgen.cpp tracepointgen.h
+ parser.cpp parser.h
+)
+qt_internal_return_unless_building_tools()
diff --git a/src/tools/tracepointgen/parser.cpp b/src/tools/tracepointgen/parser.cpp
new file mode 100644
index 0000000000..ad94b9a433
--- /dev/null
+++ b/src/tools/tracepointgen/parser.cpp
@@ -0,0 +1,609 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "tracepointgen.h"
+#include "parser.h"
+#include <qtextstream.h>
+#include <qregularexpression.h>
+#include <qfileinfo.h>
+
+static void removeOffsetRange(qsizetype begin, qsizetype end, QList<LineNumber> &offsets)
+{
+ qsizetype count = end - begin;
+ qsizetype i = 0;
+ DEBUGPRINTF2(printf("tracepointgen: removeOffsetRange: %llu %llu\n", begin, end));
+ while (i < offsets.size()) {
+ LineNumber &cur = offsets[i];
+ if (begin > cur.end) {
+ i++;
+ } else if (begin >= cur.begin && begin <= cur.end) {
+ cur.end = begin;
+ i++;
+ } else if (begin < cur.begin && end > cur.end) {
+ offsets.remove(i);
+ DEBUGPRINTF2(printf("tracepointgen: removeOffsetRange: %llu, %llu, %d\n", cur.begin, cur.end, cur.line));
+ } else if (end >= cur.begin && end <= cur.end) {
+ cur.begin = begin;
+ cur.end -= count;
+ i++;
+ } else if (end < cur.begin) {
+ cur.begin -= count;
+ cur.end -= count;
+ i++;
+ }
+ }
+}
+
+static bool findSpaceRange(const QString &data, qsizetype &offset, qsizetype &end) {
+ qsizetype cur = data.indexOf(QLatin1Char(' '), offset);
+ if (cur >= 0) {
+ qsizetype i = cur + 1;
+ while (data.constData()[i] == QLatin1Char(' ')) i++;
+ if (i - cur > 1) {
+ offset = cur;
+ end = i - 1;
+ return true;
+ }
+ cur = data.indexOf(QLatin1Char(' '), cur + 1);
+ }
+ return false;
+}
+
+static void simplifyData(QString &data, QList<LineNumber> &offsets)
+{
+ qsizetype offset = data.indexOf(QStringLiteral("//"));
+ while (offset >= 0) {
+ qsizetype endOfLine = data.indexOf(QLatin1Char('\n'), offset);
+ if (endOfLine == -1)
+ endOfLine = data.length();
+ removeOffsetRange(offset, endOfLine, offsets);
+ data.remove(offset, endOfLine - offset);
+ offset = data.indexOf(QStringLiteral("//"), offset);
+ }
+ offset = data.indexOf(QStringLiteral("/*"));
+ while (offset >= 0) {
+ qsizetype endOfComment = data.indexOf(QStringLiteral("*/"), offset);
+ if (endOfComment == -1)
+ break;
+ removeOffsetRange(offset, endOfComment + 2, offsets);
+ data.remove(offset, endOfComment - offset + 2);
+ offset = data.indexOf(QStringLiteral("/*"), offset);
+ }
+ offset = 0;
+ qsizetype end = 0;
+ data.replace(QLatin1Char('\n'), QLatin1Char(' '));
+ while (findSpaceRange(data, offset, end)) {
+ removeOffsetRange(offset, end, offsets);
+ data.remove(offset, end - offset);
+ }
+}
+
+static void simplifyData(QString &data)
+{
+ qsizetype offset = data.indexOf(QStringLiteral("//"));
+ while (offset >= 0) {
+ qsizetype endOfLine = data.indexOf(QLatin1Char('\n'), offset);
+ if (endOfLine == -1)
+ endOfLine = data.length();
+ data.remove(offset, endOfLine - offset);
+ offset = data.indexOf(QStringLiteral("//"), offset);
+ }
+ offset = data.indexOf(QStringLiteral("/*"));
+ while (offset >= 0) {
+ qsizetype endOfComment = data.indexOf(QStringLiteral("*/"), offset);
+ if (endOfComment == -1)
+ break;
+ data.remove(offset, endOfComment - offset + 2);
+ offset = data.indexOf(QStringLiteral("/*"), offset);
+ }
+ offset = 0;
+ qsizetype end = 0;
+ while (findSpaceRange(data, offset, end))
+ data.remove(offset, end - offset);
+}
+
+static QString preprocessMetadata(const QString &in)
+{
+ DEBUGPRINTF(printf("in: %s\n", qPrintable(in)));
+ QList<QString> lines = in.split(QLatin1Char('\\'));
+ QString out;
+ for (int i = 0; i < lines.size(); i++) {
+ QString l = lines.at(i).simplified();
+ DEBUGPRINTF(printf("line: %s\n", qPrintable(l)));
+ if (l.length() < 2)
+ continue;
+ if (l.startsWith(QStringLiteral("\"")))
+ l = l.right(l.length() - 1);
+ if (l.endsWith(QStringLiteral("\"")))
+ l = l.left(l.length() - 1);
+ l = l.simplified();
+
+ if (l.length() > 1) {
+ if (out.size() > 0)
+ out.append(QLatin1Char('\n'));
+ out.append(l);
+ }
+ }
+ DEBUGPRINTF(printf("out: %s\n", qPrintable(out)));
+ return out;
+}
+
+int Parser::lineNumber(qsizetype offset) const
+{
+ DEBUGPRINTF(printf("tracepointgen: lineNumber: offset %llu, line count: %llu\n", offset , m_offsets.size()));
+ for (const auto line : m_offsets) {
+ DEBUGPRINTF(printf("tracepointgen: lineNumber: %llu %llu %d\n", line.begin, line.end, line.line));
+ if (offset >= line.begin && offset <= line.end)
+ return line.line;
+ }
+ return 0;
+}
+
+void Parser::parseParamReplace(const QString &data, qsizetype offset, const QString &name)
+{
+ Replace rep;
+ qsizetype beginBrace = data.indexOf(QLatin1Char('('), offset);
+ qsizetype endBrace = data.indexOf(QLatin1Char(')'), beginBrace);
+ QString params = data.mid(beginBrace + 1, endBrace - beginBrace -1);
+ int punc = params.indexOf(QLatin1Char(','));
+ if (punc < 0)
+ panic("Syntax error in Q_TRACE_PARAM_REPLACE at file %s, line %llu", qPrintable(name), lineNumber(offset));
+ rep.in = params.left(punc).simplified();
+ rep.out = params.right(params.length() - punc - 1).simplified();
+ if (rep.in.endsWith(QLatin1Char('*')) || rep.out.endsWith(QLatin1Char(']')))
+ rep.out.append(QLatin1Char(' '));
+ DEBUGPRINTF(printf("tracepointgen: replace: %s with %s\n", qPrintable(rep.in), qPrintable(rep.out)));
+ m_replaces.push_back(rep);
+}
+
+void Parser::parseInstrument(const QString &data, qsizetype offset)
+{
+ qsizetype beginOfProvider = data.indexOf(QLatin1Char('('), offset);
+ qsizetype endOfProvider = data.indexOf(QLatin1Char(')'), beginOfProvider);
+ Function func;
+ QString provider = data.mid(beginOfProvider + 1, endOfProvider - beginOfProvider - 1).simplified();
+ if (provider != m_provider)
+ return;
+
+ qsizetype classMarker = data.indexOf(QStringLiteral("::"), endOfProvider);
+ qsizetype beginOfFunctionMarker = data.indexOf(QLatin1Char('{'), classMarker);
+ QString begin = data.mid(endOfProvider + 1, classMarker - endOfProvider - 1);
+ QString end = data.mid(classMarker + 2, beginOfFunctionMarker - classMarker - 2);
+ int spaceIndex = begin.lastIndexOf(QLatin1Char(' '));
+ if (spaceIndex == -1)
+ func.className = begin;
+ else
+ func.className = begin.mid(spaceIndex + 1, begin.length() - spaceIndex - 1);
+ qsizetype braceIndex = end.indexOf(QLatin1Char('('));
+ spaceIndex = end.indexOf(QLatin1Char(' '));
+ if (spaceIndex < braceIndex)
+ func.functionName = end.left(spaceIndex).simplified();
+ else
+ func.functionName = end.left(braceIndex).simplified();
+
+ qsizetype lastBraceIndex = end.lastIndexOf(QLatin1Char(')'));
+ func.functionParameters = end.mid(braceIndex + 1, lastBraceIndex - braceIndex - 1).simplified();
+
+ DEBUGPRINTF(printf("tracepointgen: %s(%s)\n", qPrintable(func.functionName), qPrintable(func.functionParameters)));
+
+ m_functions.push_back(func);
+}
+
+void Parser::parsePoint(const QString &data, qsizetype offset)
+{
+ qsizetype beginOfProvider = data.indexOf(QLatin1Char('('), offset);
+ qsizetype endOfProvider = data.indexOf(QLatin1Char(','), beginOfProvider);
+ Point point;
+ QString provider = data.mid(beginOfProvider + 1, endOfProvider - beginOfProvider - 1).simplified();
+ if (provider != m_provider)
+ return;
+
+ qsizetype endOfPoint = data.indexOf(QLatin1Char(','), endOfProvider + 1);
+ qsizetype endOfPoint2 = data.indexOf(QLatin1Char(')'), endOfProvider + 1);
+ bool params = true;
+ if (endOfPoint == -1 || endOfPoint2 < endOfPoint) {
+ endOfPoint = endOfPoint2;
+ params = false;
+ }
+ point.name = data.mid(endOfProvider + 1, endOfPoint - endOfProvider - 1).simplified();
+ if (params) {
+ int endOfParams = data.indexOf(QLatin1Char(')'), endOfPoint);
+ point.parameters = data.mid(endOfPoint + 1, endOfParams - endOfPoint - 1).simplified();
+ }
+
+ DEBUGPRINTF(printf("tracepointgen: %s(%s)\n", qPrintable(point.name), qPrintable(point.parameters)));
+
+ m_points.push_back(point);
+}
+
+void Parser::parsePrefix(const QString &data, qsizetype offset)
+{
+ qsizetype beginOfProvider = data.indexOf(QLatin1Char('('), offset);
+ qsizetype endOfProvider = data.indexOf(QLatin1Char(','), beginOfProvider);
+ QString prefix;
+ QString provider = data.mid(beginOfProvider + 1, endOfProvider - beginOfProvider - 1).simplified();
+ if (provider != m_provider)
+ return;
+
+ qsizetype endOfPoint = data.indexOf(QLatin1Char(')'), endOfProvider + 1);
+ prefix = data.mid(endOfProvider + 1, endOfPoint - endOfProvider - 1).simplified();
+
+ DEBUGPRINTF(printf("tracepointgen: prefix: %s\n", qPrintable(prefix)));
+
+ if (!m_prefixes.contains(prefix))
+ m_prefixes.push_back(preprocessMetadata(prefix));
+}
+
+QStringList Parser::findEnumValues(const QString &name, const QStringList &includes)
+{
+ QStringList split = name.split(QStringLiteral("::"));
+ QString enumName = split.last();
+ DEBUGPRINTF(printf("searching for %s\n", qPrintable(name)));
+ QStringList ret;
+ for (const QString &filename : includes) {
+ QFile input(filename);
+ if (!input.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ DEBUGPRINTF(printf("Cannot open '%s' for reading: %s\n",
+ qPrintable(filename), qPrintable(input.errorString())));
+ return ret;
+ }
+ QString data;
+ QTextStream stream(&input);
+ while (!stream.atEnd()) {
+ QString line = stream.readLine().trimmed();
+ data += line + QLatin1Char('\n');
+ }
+ simplifyData(data);
+
+ int pos = 0;
+ bool valid = true;
+ for (int i = 0; i < split.size() - 1; i++) {
+ QRegularExpression macro(QStringLiteral("(struct|class|namespace) +([A-Za-z0-9_]*)? +([A-Za-z0-9]*;?)"));
+ QRegularExpressionMatchIterator m = macro.globalMatch(data);
+ bool found = false;
+ while (m.hasNext() && !found) {
+ QRegularExpressionMatch match = m.next();
+ QString n = match.captured(2);
+ if (!n.endsWith(QLatin1Char(';')) && n == split[i] && match.capturedStart(2) > pos) {
+ pos = match.capturedStart(2);
+ found = true;
+ break;
+ }
+ if (match.hasCaptured(3)) {
+ n = match.captured(3);
+ if (!n.endsWith(QLatin1Char(';')) && n == split[i] && match.capturedStart(3) > pos) {
+ pos = match.capturedStart(3);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid) {
+ QRegularExpression macro(QStringLiteral("enum +([A-Za-z0-9_]*)"));
+ QRegularExpressionMatchIterator m = macro.globalMatch(data);
+ while (m.hasNext()) {
+ QRegularExpressionMatch match = m.next();
+
+ if (match.capturedStart() < pos)
+ continue;
+
+ QString n = match.captured(1);
+
+ if (n == enumName) {
+ DEBUGPRINTF(printf("Found enum: %s\n", qPrintable(n)));
+ int begin = data.indexOf(QLatin1Char('{'), match.capturedEnd());
+ int end = data.indexOf(QLatin1Char('}'), begin);
+ QString block = data.mid(begin + 1, end - begin - 1);
+ const QStringList enums = block.split(QLatin1Char('\n'));
+ for (const auto &e : enums) {
+ const auto trimmed = e.trimmed();
+ if (!trimmed.isEmpty() && !trimmed.startsWith(QLatin1Char('#')))
+ ret << trimmed;
+ }
+
+ return ret;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+struct EnumNameValue
+{
+ QString name;
+ QString valueStr;
+ int value;
+};
+
+static QList<EnumNameValue> enumsToValues(const QStringList &values)
+{
+ int cur = 0;
+ QList<EnumNameValue> ret;
+ for (const QString &value : values) {
+ EnumNameValue r;
+ if (value.contains(QLatin1Char('='))) {
+ size_t offset = value.indexOf(QLatin1Char('='));
+ r.name = value.left(offset).trimmed();
+ QString val = value.right(value.length() - offset - 1).trimmed();
+ if (val.endsWith(QLatin1Char(',')))
+ val = val.left(val.length() - 1);
+ bool valid = false;
+ int integer = val.toInt(&valid);
+ if (!valid)
+ integer = val.toInt(&valid, 16);
+ if (valid) {
+ cur = r.value = integer;
+ ret << r;
+ } else {
+ auto iter = std::find_if(ret.begin(), ret.end(), [&val](const EnumNameValue &elem){
+ return elem.name == val;
+ });
+ if (iter != ret.end()) {
+ cur = r.value = iter->value;
+ ret << r;
+ } else {
+ DEBUGPRINTF(printf("Invalid value: %s %s\n", qPrintable(r.name), qPrintable(value)));
+ }
+ }
+ } else {
+ if (value.endsWith(QLatin1Char(',')))
+ r.name = value.left(value.length() - 1);
+ else
+ r.name = value;
+ r.value = ++cur;
+ ret << r;
+ }
+ }
+ return ret;
+}
+
+void Parser::parseMetadata(const QString &data, qsizetype offset, const QStringList &includes)
+{
+ qsizetype beginOfProvider = data.indexOf(QLatin1Char('('), offset);
+ qsizetype endOfProvider = data.indexOf(QLatin1Char(','), beginOfProvider);
+ QString metadata;
+ QString provider = data.mid(beginOfProvider + 1, endOfProvider - beginOfProvider - 1).simplified();
+ if (provider != m_provider)
+ return;
+
+ qsizetype endOfPoint = data.indexOf(QLatin1Char(')'), endOfProvider + 1);
+ metadata = data.mid(endOfProvider + 1, endOfPoint - endOfProvider - 1).simplified();
+
+ DEBUGPRINTF(printf("tracepointgen: metadata: %s", qPrintable(metadata)));
+
+ QString preprocessed = preprocessMetadata(metadata);
+
+ DEBUGPRINTF2(printf("preprocessed %s\n", qPrintable(preprocessed)));
+
+ QRegularExpression macro(QStringLiteral("([A-Z]*) ?{ ?([A-Za-z0-9=_,. ]*) ?} ?([A-Za-z0-9_:]*) ?;"));
+ QRegularExpressionMatchIterator i = macro.globalMatch(preprocessed);
+ qsizetype prev = 0;
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+ QString values = match.captured(2).trimmed();
+ int cur = match.capturedStart();
+ if (cur > prev)
+ m_metadata.append(preprocessed.mid(prev, cur - prev));
+
+ prev = match.capturedEnd() + 1;
+ DEBUGPRINTF2(printf("values: %s\n", qPrintable(values)));
+ if (values.isEmpty() || values.startsWith(QStringLiteral("AUTO"))) {
+ values.replace(QLatin1Char('\n'), QLatin1Char(' '));
+ QStringList ranges;
+ if (values.contains(QStringLiteral("RANGE"))) {
+ QRegularExpression rangeMacro(QStringLiteral("RANGE +([A-Za-z0-9_]*) +... +([A-Za-z0-9_]*)"));
+ QRegularExpressionMatchIterator r = rangeMacro.globalMatch(values);
+ while (r.hasNext()) {
+ QRegularExpressionMatch rm = r.next();
+ ranges << rm.captured(1);
+ ranges << rm.captured(2);
+ DEBUGPRINTF2(printf("range: %s ... %s\n", qPrintable(rm.captured(1)), qPrintable(rm.captured(2))));
+ }
+ }
+
+ const auto enumOrFlag = match.captured(1);
+ const auto name = match.captured(3);
+ const bool flags = enumOrFlag == QStringLiteral("FLAGS");
+
+ QStringList values = findEnumValues(name, includes);
+ if (values.isEmpty()) {
+ if (flags && name.endsWith(QLatin1Char('s')))
+ values = findEnumValues(name.left(name.length() - 1), includes);
+ if (values.isEmpty()) {
+ DEBUGPRINTF(printf("Unable to find values for %s\n", qPrintable(name)));
+ }
+ }
+ if (!values.isEmpty()) {
+ auto moreValues = enumsToValues(values);
+ if (ranges.size()) {
+ for (int i = 0; i < ranges.size() / 2; i++) {
+ bool rangeFound = false;
+ for (auto &v : moreValues) {
+ if (v.name == ranges[2 * i]) {
+ rangeFound = true;
+ QString rangeEnd = ranges[2 * i + 1];
+ auto iter = std::find_if(moreValues.begin(), moreValues.end(), [&rangeEnd](const EnumNameValue &elem){
+ return elem.name == rangeEnd;
+ });
+ if (iter != moreValues.end())
+ v.valueStr = QStringLiteral("RANGE(%1, %2 ... %3)").arg(v.name).arg(v.value).arg(iter->value);
+ else
+ panic("Unable to find range end: %s\n", qPrintable(rangeEnd));
+ break;
+ }
+ }
+ if (rangeFound == false)
+ panic("Unable to find range begin: %s\n", qPrintable(ranges[2 * i]));
+ }
+ }
+ std::sort(moreValues.begin(), moreValues.end(), [](const EnumNameValue &a, const EnumNameValue &b) {
+ return a.value < b.value;
+ });
+ values.clear();
+ int prevValue = std::as_const(moreValues).front().value;
+ for (const auto &v : std::as_const(moreValues)) {
+ QString a;
+ if (v.valueStr.isNull()) {
+ if (v.value == prevValue + 1 && !flags)
+ a = v.name;
+ else
+ a = QStringLiteral("%1 = %2").arg(v.name).arg(v.value);
+ prevValue = v.value;
+ } else {
+ a = v.valueStr;
+ }
+ values << a;
+ }
+
+ metadata = QStringLiteral("%1 {\n %2 \n} %3;").arg(enumOrFlag).arg(values.join(QStringLiteral(",\n"))).arg(name);
+ if (!m_metadata.contains(metadata))
+ m_metadata.append(metadata);
+ }
+ } else {
+ if (!m_metadata.contains(match.captured()))
+ m_metadata.append(match.captured());
+ }
+ }
+ if (prev < preprocessed.length())
+ m_metadata.append(preprocessed.mid(prev, preprocessed.length() - prev));
+}
+
+QString Parser::resolveInclude(const QString &filename)
+{
+ QFileInfo info(filename);
+ if (info.exists())
+ return info.absoluteFilePath();
+ for (const QString &sp : std::as_const(m_includeDirs)) {
+ info = QFileInfo(sp + QLatin1Char('/') + filename);
+ if (info.exists())
+ return info.absoluteFilePath();
+ }
+ return {};
+}
+
+void Parser::addIncludesRecursive(const QString &filename, QList<QString> &includes)
+{
+ QFileInfo info(filename);
+ DEBUGPRINTF(printf("check include: %s\n", qPrintable(filename)));
+ QFile input(filename);
+ if (!input.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ DEBUGPRINTF(printf("Cannot open '%s' for reading: %s\n",
+ qPrintable(filename), qPrintable(input.errorString())));
+ return;
+ }
+ QString data;
+ QTextStream stream(&input);
+ while (!stream.atEnd()) {
+ QString line = stream.readLine().trimmed();
+ data += line + QLatin1Char(QLatin1Char('\n'));
+ }
+
+ QRegularExpression includeMacro(QStringLiteral("#include [\"<]([A-Za-z0-9_./]*.h)[\">]"));
+ QRegularExpressionMatchIterator i = includeMacro.globalMatch(data);
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+ QString filename = match.captured(1);
+
+ QString rinc = filename;
+ if (filename.startsWith(QStringLiteral("../"))) {
+ QFileInfo info2(info.absolutePath() + QLatin1Char('/') + filename);
+ if (!info2.exists()) {
+ DEBUGPRINTF(printf("unable to find %s\n", qPrintable(filename)));
+ continue;
+ }
+ rinc = info2.absoluteFilePath();
+ filename = info2.fileName();
+ }
+
+ // only search possible qt headers
+ if (filename.startsWith(QLatin1Char('q'), Qt::CaseInsensitive)) {
+ QString resolved = resolveInclude(rinc);
+ if (!resolved.isEmpty() && !includes.contains(resolved)) {
+ includes.push_back(resolved);
+ addIncludesRecursive(resolved, includes);
+ }
+ }
+ }
+}
+
+void Parser::parse(QIODevice &input, const QString &name)
+{
+ QString data;
+ QTextStream stream(&input);
+ int lineNumber = 1;
+ qsizetype prev = 0;
+ while (!stream.atEnd()) {
+ QString line = stream.readLine().trimmed();
+ m_offsets.push_back({prev, prev + line.length(), lineNumber++});
+ prev += line.length() + 1;
+ data += line + QLatin1Char(QLatin1Char('\n'));
+ }
+
+ simplifyData(data, m_offsets);
+
+ QStringList includes;
+
+ QRegularExpression includeMacro(QStringLiteral("#include [\"<]([A-Za-z0-9_./]*.h)[\">]"));
+ QRegularExpressionMatchIterator i = includeMacro.globalMatch(data);
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+ const QString filename = match.captured(1);
+ // only search possible qt headers
+ if (filename.startsWith(QLatin1Char('q'), Qt::CaseInsensitive)) {
+ const QString resolved = resolveInclude(filename);
+ if (!resolved.isEmpty() && !includes.contains(resolved)) {
+ includes.push_back(resolved);
+ addIncludesRecursive(resolved, includes);
+ }
+ }
+ }
+
+ QRegularExpression traceMacro(QStringLiteral("Q_TRACE_([A-Z_]*)"));
+ i = traceMacro.globalMatch(data);
+ while (i.hasNext()) {
+ QRegularExpressionMatch match = i.next();
+
+ QString macroType = match.captured(1);
+ if (macroType == QStringLiteral("PARAM_REPLACE"))
+ parseParamReplace(data, match.capturedEnd(), name);
+ else if (macroType == QStringLiteral("INSTRUMENT"))
+ parseInstrument(data, match.capturedEnd());
+ else if (macroType == QStringLiteral("POINT"))
+ parsePoint(data, match.capturedEnd());
+ else if (macroType == QStringLiteral("PREFIX"))
+ parsePrefix(data, match.capturedEnd());
+ else if (macroType == QStringLiteral("METADATA"))
+ parseMetadata(data, match.capturedEnd(), includes);
+ }
+
+ for (auto &func : m_functions) {
+ for (auto &rep : m_replaces)
+ func.functionParameters.replace(rep.in, rep.out);
+ }
+}
+
+void Parser::write(QIODevice &input) const
+{
+ QTextStream out(&input);
+ if (m_prefixes.size() > 0) {
+ out << QStringLiteral("{\n");
+ for (const auto &prefix : m_prefixes)
+ out << prefix << "\n";
+ out << QStringLiteral("}\n");
+ }
+ for (const auto &m : m_metadata)
+ out << m << "\n";
+ for (const auto &func : m_functions) {
+ out << func.className << "_" << func.functionName << "_entry(" << func.functionParameters << ")\n";
+ out << func.className << "_" << func.functionName << "_exit()\n";
+ }
+ for (const auto &point : m_points)
+ out << point.name << "(" << point.parameters << ")\n";
+}
diff --git a/src/tools/tracepointgen/parser.h b/src/tools/tracepointgen/parser.h
new file mode 100644
index 0000000000..389734983d
--- /dev/null
+++ b/src/tools/tracepointgen/parser.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <qiodevice.h>
+#include <qlist.h>
+#include <qbytearray.h>
+
+struct Function
+{
+ QString className;
+ QString functionName;
+ QString functionParameters;
+};
+
+struct Point
+{
+ QString name;
+ QString parameters;
+};
+
+struct Replace
+{
+ QString in;
+ QString out;
+};
+
+struct LineNumber
+{
+ qsizetype begin;
+ qsizetype end;
+ int line;
+};
+
+struct Parser
+{
+ Parser(const QString &provider)
+ : m_provider(provider)
+ {
+
+ }
+
+ void addIncludeDirs(const QStringList &list)
+ {
+ m_includeDirs.append(list);
+ }
+ QString resolveInclude(const QString &filename);
+ void addIncludesRecursive(const QString &filename, QStringList &includes);
+ QStringList findEnumValues(const QString &name, const QStringList &includes);
+
+ void parseParamReplace(const QString &data, qsizetype offset, const QString &name);
+ void parseInstrument(const QString &data, qsizetype offset);
+ void parsePoint(const QString &data, qsizetype offset);
+ void parsePrefix(const QString &data, qsizetype offset);
+ void parseMetadata(const QString &data, qsizetype offset, const QStringList &includes);
+ int lineNumber(qsizetype offset) const;
+
+ void parse(QIODevice &input, const QString &name);
+ void write(QIODevice &input) const;
+ bool isEmpty() const
+ {
+ return m_functions.isEmpty() && m_points.isEmpty();
+ }
+
+ QList<Function> m_functions;
+ QList<Point> m_points;
+ QList<Replace> m_replaces;
+ QList<QString> m_prefixes;
+ QList<QString> m_metadata;
+ QList<LineNumber> m_offsets;
+ QList<QString> m_includeDirs;
+ QString m_provider;
+};
+
+#endif // PARSER_H
diff --git a/src/tools/tracepointgen/tracepointgen.cpp b/src/tools/tracepointgen/tracepointgen.cpp
new file mode 100644
index 0000000000..d814c69873
--- /dev/null
+++ b/src/tools/tracepointgen/tracepointgen.cpp
@@ -0,0 +1,69 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfile.h>
+
+#include "tracepointgen.h"
+#include "parser.h"
+
+static void usage(int status)
+{
+ printf("Generates a tracepoint file for tracegen tool from input files.\n\n");
+ printf("Usage: tracepointgen <output file> <input files> \n");
+ exit(status);
+}
+
+static void parseArgs(int argc, char *argv[], QString &provider, QString &outFile, QList<QString> &inputFiles)
+{
+ if (argc == 1)
+ usage(0);
+ if (argc < 4)
+ usage(-1);
+
+ provider = QLatin1StringView(argv[1]);
+ outFile = QLatin1StringView(argv[2]);
+ for (int i = 3; i < argc; i++)
+ inputFiles.append(QLatin1StringView(argv[i]));
+}
+
+int main(int argc, char *argv[])
+{
+ QString provider;
+ QList<QString> inputFiles;
+ QString outFile;
+
+ parseArgs(argc, argv, provider, outFile, inputFiles);
+
+ Parser parser(provider);
+
+ for (const QString &inputFile : inputFiles) {
+ if (inputFile.startsWith(QLatin1Char('I'))) {
+ QStringList includeDirs = inputFile.right(inputFile.length() - 1).split(QLatin1Char(';'));
+ parser.addIncludeDirs(includeDirs);
+ continue;
+ }
+ QFile in(inputFile);
+ if (!in.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ panic("Cannot open '%s' for reading: %s\n",
+ qPrintable(inputFile), qPrintable(in.errorString()));
+ }
+ DEBUGPRINTF(printf("tracepointgen: parse %s\n", qPrintable(inputFile)));
+ parser.parse(in, inputFile);
+ }
+ if (parser.isEmpty())
+ panic("empty provider %s\n", qPrintable(provider));
+
+ QFile out(outFile);
+
+ if (!out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ panic("Cannot open '%s' for writing: %s\n",
+ qPrintable(outFile), qPrintable(out.errorString()));
+ }
+
+ parser.write(out);
+ out.close();
+
+ return 0;
+}
diff --git a/src/tools/tracepointgen/tracepointgen.h b/src/tools/tracepointgen/tracepointgen.h
new file mode 100644
index 0000000000..6aed3dc574
--- /dev/null
+++ b/src/tools/tracepointgen/tracepointgen.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef TRACEPOINTGEN_H
+#define TRACEPOINTGEN_H
+
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+
+#define DEBUG_TRACEPOINTGEN 0
+
+#if DEBUG_TRACEPOINTGEN > 0
+ #define DEBUGPRINTF(x) x
+ #if (DEBUG_TRACEPOINTGEN > 1)
+ #define DEBUGPRINTF2(x) x
+ #else
+ #define DEBUGPRINTF2(x)
+ #endif
+#else
+ #define DEBUGPRINTF(x)
+ #define DEBUGPRINTF2(x)
+#endif
+
+
+
+inline void panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "tracepointgen: fatal: ");
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fputc('\n', stderr);
+
+ exit(EXIT_FAILURE);
+}
+
+#endif
diff --git a/src/tools/uic/CMakeLists.txt b/src/tools/uic/CMakeLists.txt
index aab6ecfe28..9f47ec8b4b 100644
--- a/src/tools/uic/CMakeLists.txt
+++ b/src/tools/uic/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from uic.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## uic Tool:
@@ -6,9 +7,10 @@
qt_get_tool_target_name(target_name uic)
qt_internal_add_tool(${target_name}
+ TRY_RUN
TARGET_DESCRIPTION "Qt User Interface Compiler"
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Widgets # special case
+ TOOLS_TARGET Widgets
SOURCES
cpp/cppwritedeclaration.cpp cpp/cppwritedeclaration.h
cpp/cppwriteincludes.cpp cpp/cppwriteincludes.h
@@ -30,6 +32,7 @@ qt_internal_add_tool(${target_name}
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_FOREACH
+ QT_USE_NODISCARD_FILE_OPEN
QT_UIC
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
@@ -37,14 +40,5 @@ qt_internal_add_tool(${target_name}
cpp
python
shared
- #PUBLIC_LIBRARIES # special case remove
- #Qt::Gui # special case remove
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:uic.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Qt User Interface Compiler"
-# _OPTION = "host_build"
-
-## Scopes:
-#####################################################################
diff --git a/src/tools/uic/cpp/cppwritedeclaration.cpp b/src/tools/uic/cpp/cppwritedeclaration.cpp
index 995b99b692..8261963cfa 100644
--- a/src/tools/uic/cpp/cppwritedeclaration.cpp
+++ b/src/tools/uic/cpp/cppwritedeclaration.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppwritedeclaration.h"
#include "cppwriteinitialization.h"
@@ -39,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace {
void openNameSpaces(const QStringList &namespaceList, QTextStream &output)
{
@@ -75,10 +52,10 @@ void WriteDeclaration::acceptUI(DomUI *node)
QString exportMacro = node->elementExportMacro();
if (!exportMacro.isEmpty())
- exportMacro.append(QLatin1Char(' '));
+ exportMacro.append(u' ');
- QStringList namespaceList = qualifiedClassName.split(QLatin1String("::"));
- if (namespaceList.count()) {
+ QStringList namespaceList = qualifiedClassName.split("::"_L1);
+ if (namespaceList.size()) {
className = namespaceList.last();
namespaceList.removeLast();
}
@@ -88,15 +65,15 @@ void WriteDeclaration::acceptUI(DomUI *node)
// is a User using Qt-in-namespace having his own classes not in a namespace.
// In this case the generated Ui helper classes will also end up in
// the Qt namespace (which is harmless, but not "pretty")
- const bool needsMacro = namespaceList.count() == 0
- || namespaceList[0] == QLatin1String("qdesigner_internal");
+ const bool needsMacro = m_option.qtNamespace &&
+ (namespaceList.size() == 0 || namespaceList[0] == "qdesigner_internal"_L1);
if (needsMacro)
m_output << "QT_BEGIN_NAMESPACE\n\n";
openNameSpaces(namespaceList, m_output);
- if (namespaceList.count())
+ if (namespaceList.size())
m_output << "\n";
m_output << "class " << exportMacro << m_option.prefix << className << "\n"
@@ -105,7 +82,7 @@ void WriteDeclaration::acceptUI(DomUI *node)
const QStringList connections = m_uic->databaseInfo()->connections();
for (const QString &connection : connections) {
- if (connection != QLatin1String("(default)"))
+ if (connection != "(default)"_L1)
m_output << m_option.indent << "QSqlDatabase " << connection << "Connection;\n";
}
@@ -121,11 +98,11 @@ void WriteDeclaration::acceptUI(DomUI *node)
closeNameSpaces(namespaceList, m_output);
- if (namespaceList.count())
+ if (namespaceList.size())
m_output << "\n";
if (m_option.generateNamespace && !m_option.prefix.isEmpty()) {
- namespaceList.append(QLatin1String("Ui"));
+ namespaceList.append("Ui"_L1);
openNameSpaces(namespaceList, m_output);
@@ -133,7 +110,7 @@ void WriteDeclaration::acceptUI(DomUI *node)
closeNameSpaces(namespaceList, m_output);
- if (namespaceList.count())
+ if (namespaceList.size())
m_output << "\n";
}
@@ -143,7 +120,7 @@ void WriteDeclaration::acceptUI(DomUI *node)
void WriteDeclaration::acceptWidget(DomWidget *node)
{
- QString className = QLatin1String("QWidget");
+ QString className = u"QWidget"_s;
if (node->hasAttributeClass())
className = node->attributeClass();
@@ -160,7 +137,7 @@ void WriteDeclaration::acceptSpacer(DomSpacer *node)
void WriteDeclaration::acceptLayout(DomLayout *node)
{
- QString className = QLatin1String("QLayout");
+ QString className = u"QLayout"_s;
if (node->hasAttributeClass())
className = node->attributeClass();
diff --git a/src/tools/uic/cpp/cppwritedeclaration.h b/src/tools/uic/cpp/cppwritedeclaration.h
index f83bfe8f50..2dcb5981e1 100644
--- a/src/tools/uic/cpp/cppwritedeclaration.h
+++ b/src/tools/uic/cpp/cppwritedeclaration.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CPPWRITEDECLARATION_H
#define CPPWRITEDECLARATION_H
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index 809c78f700..7cf7c4e59e 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppwriteincludes.h"
#include "driver.h"
@@ -40,6 +15,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
enum { debugWriteIncludes = 0 };
enum { warnHeaderGeneration = 0 };
@@ -47,7 +24,7 @@ enum { warnHeaderGeneration = 0 };
static inline QString moduleHeader(const QString &module, const QString &header)
{
QString rc = module;
- rc += QLatin1Char('/');
+ rc += u'/';
rc += header;
return rc;
}
@@ -60,11 +37,11 @@ WriteIncludes::WriteIncludes(Uic *uic) : WriteIncludesBase(uic),
// When possible (no namespace) use the "QtModule/QClass" convention
// and create a re-mapping of the old header "qclass.h" to it. Do not do this
// for the "Phonon::Someclass" classes, however.
- const QString namespaceDelimiter = QLatin1String("::");
+ const QLatin1StringView namespaceDelimiter = "::"_L1;
for (const auto &e : classInfoEntries()) {
- const QString klass = QLatin1String(e.klass);
- const QString module = QLatin1String(e.module);
- QLatin1String header = QLatin1String(e.header);
+ const QString klass = QLatin1StringView(e.klass);
+ const QString module = QLatin1StringView(e.module);
+ QLatin1StringView header = QLatin1StringView(e.header);
if (klass.contains(namespaceDelimiter)) {
m_classToHeader.insert(klass, moduleHeader(module, header));
} else {
@@ -113,7 +90,7 @@ void WriteIncludes::insertIncludeForClass(const QString &className, QString head
// Quick check by class name to detect includehints provided for custom widgets.
// Remove namespaces
QString lowerClassName = className.toLower();
- static const QString namespaceSeparator = QLatin1String("::");
+ static const auto namespaceSeparator = "::"_L1;
const int namespaceIndex = lowerClassName.lastIndexOf(namespaceSeparator);
if (namespaceIndex != -1)
lowerClassName.remove(0, namespaceIndex + namespaceSeparator.size());
@@ -126,7 +103,7 @@ void WriteIncludes::insertIncludeForClass(const QString &className, QString head
if (!uic()->option().implicitIncludes)
break;
header = lowerClassName;
- header += QLatin1String(".h");
+ header += ".h"_L1;
if (warnHeaderGeneration) {
qWarning("%s: Warning: generated header '%s' for class '%s'.",
qPrintable(uic()->option().messagePrefix()),
@@ -157,7 +134,7 @@ void WriteIncludes::addCppCustomWidget(const QString &className, const DomCustom
QString header;
bool global = false;
if (!m_classToHeader.contains(className)) {
- global = domHeader->attributeLocation().toLower() == QLatin1String("global");
+ global = domHeader->attributeLocation().toLower() == "global"_L1;
header = domHeader->text();
}
insertIncludeForClass(className, header, global);
@@ -169,7 +146,7 @@ void WriteIncludes::acceptInclude(DomInclude *node)
{
bool global = true;
if (node->hasAttributeLocation())
- global = node->attributeLocation() == QLatin1String("global");
+ global = node->attributeLocation() == "global"_L1;
insertInclude(node->text(), global);
}
@@ -190,8 +167,8 @@ void WriteIncludes::insertInclude(const QString &header, bool global)
void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global)
{
- const QChar openingQuote = global ? QLatin1Char('<') : QLatin1Char('"');
- const QChar closingQuote = global ? QLatin1Char('>') : QLatin1Char('"');
+ const QChar openingQuote = global ? u'<' : u'"';
+ const QChar closingQuote = global ? u'>' : u'"';
// Check for the old headers 'qslider.h' and replace by 'QtGui/QSlider'
for (const QString &header : headers) {
diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h
index 4ff2a514fb..1ec10f39b2 100644
--- a/src/tools/uic/cpp/cppwriteincludes.h
+++ b/src/tools/uic/cpp/cppwriteincludes.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CPPWRITEINCLUDES_H
#define CPPWRITEINCLUDES_H
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 7f5776b5c6..205d6a50a9 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cppwriteinitialization.h"
#include "customwidgetsinfo.h"
@@ -46,17 +21,47 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace {
+
+ // Expand "Horizontal", "Qt::Horizontal" to "Qt::Orientation::Horizontal"
+ QString expandEnum(QString value, const QString &prefix)
+ {
+ if (value.startsWith(prefix))
+ return value;
+ const auto pos = value.lastIndexOf("::"_L1);
+ if (pos == -1)
+ return prefix + "::"_L1 + value;
+ value.replace(0, pos, prefix);
+ return value;
+ }
+
+ inline QString expandSizePolicyEnum(const QString &value)
+ {
+ return expandEnum(value, "QSizePolicy::Policy"_L1);
+ }
+
+ inline QString expandToolBarArea(const QString &value)
+ {
+ return expandEnum(value, "Qt::ToolBarArea"_L1);
+ }
+
+ inline QString expandDockWidgetArea(const QString &value)
+ {
+ return expandEnum(value, "Qt::DockWidgetArea"_L1);
+ }
+
// figure out the toolbar area of a DOM attrib list.
// By legacy, it is stored as an integer. As of 4.3.0, it is the enumeration value.
QString toolBarAreaStringFromDOMAttributes(const CPP::WriteInitialization::DomPropertyMap &attributes) {
- const DomProperty *pstyle = attributes.value(QLatin1String("toolBarArea"));
+ const DomProperty *pstyle = attributes.value("toolBarArea"_L1);
QString result;
if (!pstyle)
return result;
switch (pstyle->kind()) {
case DomProperty::Number:
- result = QLatin1String(language::toolbarArea(pstyle->elementNumber()));
+ result = language::toolbarArea(pstyle->elementNumber());
break;
case DomProperty::Enum:
result = pstyle->elementEnum();
@@ -64,9 +69,7 @@ namespace {
default:
break;
}
- if (!result.startsWith(QLatin1String("Qt::")))
- result.prepend(QLatin1String("Qt::"));
- return result + QLatin1String(", ");
+ return expandToolBarArea(result) + ", "_L1;
}
// Write a statement to create a spacer item.
@@ -76,7 +79,7 @@ namespace {
int w = 0;
int h = 0;
- if (const DomProperty *sh = properties.value(QLatin1String("sizeHint"))) {
+ if (const DomProperty *sh = properties.value("sizeHint"_L1)) {
if (const DomSize *sizeHint = sh->elementSize()) {
w = sizeHint->elementWidth();
h = sizeHint->elementHeight();
@@ -85,27 +88,17 @@ namespace {
output << w << ", " << h << ", ";
// size type
- QString sizeType;
- if (const DomProperty *st = properties.value(QLatin1String("sizeType"))) {
- const QString value = st->elementEnum();
- if (value.startsWith(QLatin1String("QSizePolicy::")))
- sizeType = value;
- else
- sizeType = QLatin1String("QSizePolicy::") + value;
- } else {
- sizeType = QStringLiteral("QSizePolicy::Expanding");
- }
+ const DomProperty *st = properties.value("sizeType"_L1);
+ QString horizType = st != nullptr ? st->elementEnum() : "Expanding"_L1;
+ QString vertType = "Minimum"_L1;
// orientation
- bool isVspacer = false;
- if (const DomProperty *o = properties.value(QLatin1String("orientation"))) {
- const QString orientation = o->elementEnum();
- if (orientation == QLatin1String("Qt::Vertical") || orientation == QLatin1String("Vertical"))
- isVspacer = true;
- }
- const QString horizType = isVspacer ? QLatin1String("QSizePolicy::Minimum") : sizeType;
- const QString vertType = isVspacer ? sizeType : QLatin1String("QSizePolicy::Minimum");
- output << language::enumValue(horizType) << ", " << language::enumValue(vertType) << ')';
+ const DomProperty *o = properties.value("orientation"_L1);
+ if (o != nullptr && o->elementEnum().endsWith("Vertical"_L1))
+ std::swap(horizType, vertType);
+
+ output << language::enumValue(expandSizePolicyEnum(horizType)) << ", "
+ << language::enumValue(expandSizePolicyEnum(vertType)) << ')';
}
@@ -146,7 +139,7 @@ namespace {
if (p->attributeName() == u"features"
&& customWidgetsInfo->extends(className, "QDockWidget")
&& p->elementSet() == u"QDockWidget::AllDockWidgetFeatures") {
- const QString msg = fileName + QLatin1String(": Warning: Deprecated enum value QDockWidget::AllDockWidgetFeatures was encountered.");
+ const QString msg = fileName + ": Warning: Deprecated enum value QDockWidget::AllDockWidgetFeatures was encountered."_L1;
qWarning("%s", qPrintable(msg));
return false;
}
@@ -155,7 +148,7 @@ namespace {
if (p->attributeName() == u"sizeAdjustPolicy"
&& customWidgetsInfo->extends(className, "QComboBox")
&& p->elementEnum() == u"QComboBox::AdjustToMinimumContentsLength") {
- const QString msg = fileName + QLatin1String(": Warning: Deprecated enum value QComboBox::AdjustToMinimumContentsLength was encountered.");
+ const QString msg = fileName + ": Warning: Deprecated enum value QComboBox::AdjustToMinimumContentsLength was encountered."_L1;
qWarning("%s", qPrintable(msg));
return false;
}
@@ -203,6 +196,15 @@ FontHandle::FontHandle(const DomFont *domFont) :
{
}
+static QString fontWeight(const DomFont *domFont)
+{
+ if (domFont->hasElementFontWeight())
+ return domFont->elementFontWeight();
+ if (domFont->hasElementBold())
+ return domFont->elementBold() ? u"Bold"_s : u"Normal"_s;
+ return {};
+}
+
int FontHandle::compare(const FontHandle &rhs) const
{
const QString family = m_domFont->hasElementFamily() ? m_domFont->elementFamily() : QString();
@@ -217,10 +219,10 @@ int FontHandle::compare(const FontHandle &rhs) const
if (const int crc = compareInt(pointSize, rhsPointSize))
return crc;
- const int bold = m_domFont->hasElementBold() ? (m_domFont->elementBold() ? 1 : 0) : -1;
- const int rhsBold = rhs.m_domFont->hasElementBold() ? (rhs.m_domFont->elementBold() ? 1 : 0) : -1;
- if (const int crc = compareInt(bold, rhsBold))
- return crc;
+ const QString fontWeight = CPP::fontWeight(m_domFont);
+ const QString rhsFontWeight = CPP::fontWeight(rhs.m_domFont);
+ if (const int wrc = fontWeight.compare(rhsFontWeight))
+ return wrc;
const int italic = m_domFont->hasElementItalic() ? (m_domFont->elementItalic() ? 1 : 0) : -1;
const int rhsItalic = rhs.m_domFont->hasElementItalic() ? (rhs.m_domFont->elementItalic() ? 1 : 0) : -1;
@@ -232,11 +234,6 @@ int FontHandle::compare(const FontHandle &rhs) const
if (const int crc = compareInt(underline, rhsUnderline))
return crc;
- const int weight = m_domFont->hasElementWeight() ? m_domFont->elementWeight() : -1;
- const int rhsWeight = rhs.m_domFont->hasElementWeight() ? rhs.m_domFont->elementWeight() : -1;
- if (const int crc = compareInt(weight, rhsWeight))
- return crc;
-
const int strikeOut = m_domFont->hasElementStrikeOut() ? (m_domFont->elementStrikeOut() ? 1 : 0) : -1;
const int rhsStrikeOut = rhs.m_domFont->hasElementStrikeOut() ? (rhs.m_domFont->elementStrikeOut() ? 1 : 0) : -1;
if (const int crc = compareInt(strikeOut, rhsStrikeOut))
@@ -258,6 +255,13 @@ int FontHandle::compare(const FontHandle &rhs) const
if (const int src = styleStrategy.compare(rhsStyleStrategy))
return src;
+ const QString hintingPreference = m_domFont->hasElementHintingPreference()
+ ? m_domFont->elementHintingPreference() : QString();
+ const QString rhsHintingPreference = rhs.m_domFont->hasElementHintingPreference()
+ ? rhs.m_domFont->elementHintingPreference() : QString();
+ if (const int src = hintingPreference.compare(rhsHintingPreference))
+ return src;
+
return 0;
}
@@ -388,12 +392,12 @@ void WriteInitialization::LayoutDefaultHandler::acceptLayoutFunction(DomLayoutFu
if (node->hasAttributeMargin()) {
m_state[Margin] |= HasDefaultFunction;
m_functions[Margin] = node->attributeMargin();
- m_functions[Margin] += QLatin1String("()");
+ m_functions[Margin] += "()"_L1;
}
if (node->hasAttributeSpacing()) {
m_state[Spacing] |= HasDefaultFunction;
m_functions[Spacing] = node->attributeSpacing();
- m_functions[Spacing] += QLatin1String("()");
+ m_functions[Spacing] += "()"_L1;
}
}
@@ -401,7 +405,7 @@ static inline void writeContentsMargins(const QString &indent, const QString &ob
{
QString contentsMargins;
QTextStream(&contentsMargins) << value << ", " << value << ", " << value << ", " << value;
- writeSetter(indent, objectName, QLatin1String("setContentsMargins"), contentsMargins, str);
+ writeSetter(indent, objectName, "setContentsMargins"_L1, contentsMargins, str);
}
void WriteInitialization::LayoutDefaultHandler::writeProperty(int p, const QString &indent, const QString &objectName,
@@ -455,11 +459,11 @@ void WriteInitialization::LayoutDefaultHandler::writeProperties(const QString &i
// Write out properties and ignore the ones found in
// subsequent writing of the property list.
int defaultSpacing = marginType == WriteInitialization::Use43UiFile ? -1 : 6;
- writeProperty(Spacing, indent, varName, properties, QLatin1String("spacing"), QLatin1String("setSpacing"),
+ writeProperty(Spacing, indent, varName, properties, "spacing"_L1, "setSpacing"_L1,
defaultSpacing, false, str);
// We use 9 as TopLevelMargin, since Designer seem to always use 9.
static const int layoutmargins[4] = {-1, 9, 9, 0};
- writeProperty(Margin, indent, varName, properties, QLatin1String("margin"), QLatin1String("setMargin"),
+ writeProperty(Margin, indent, varName, properties, "margin"_L1, "setMargin"_L1,
layoutmargins[marginType], suppressMarginDefault, str);
}
@@ -518,16 +522,16 @@ void WriteInitialization::acceptUI(DomUI *node)
const QString widgetClassName = node->elementWidget()->attributeClass();
- const QString parameterType = widgetClassName + QLatin1String(" *");
+ const QString parameterType = widgetClassName + " *"_L1;
m_output << m_option.indent
<< language::startFunctionDefinition1("setupUi", parameterType, varName, m_option.indent);
const QStringList connections = m_uic->databaseInfo()->connections();
for (const auto &connection : connections) {
- if (connection == QLatin1String("(default)"))
+ if (connection == "(default)"_L1)
continue;
- const QString varConn = connection + QLatin1String("Connection");
+ const QString varConn = connection + "Connection"_L1;
m_output << m_indent << varConn << " = QSqlDatabase::database("
<< language::charliteral(connection, m_dindent) << ")" << language::eol;
}
@@ -536,7 +540,7 @@ void WriteInitialization::acceptUI(DomUI *node)
if (!m_buddies.empty())
m_output << language::openQtConfig(shortcutConfigKey());
- for (const Buddy &b : qAsConst(m_buddies)) {
+ for (const Buddy &b : std::as_const(m_buddies)) {
const QString buddyVarName = m_driver->widgetVariableName(b.buddyAttributeName);
if (buddyVarName.isEmpty()) {
fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
@@ -577,13 +581,13 @@ void WriteInitialization::acceptUI(DomUI *node)
if (language::language() == Language::Cpp) {
// Mark varName as unused to avoid compiler warnings.
m_refreshInitialization += m_indent;
- m_refreshInitialization += QLatin1String("(void)");
+ m_refreshInitialization += "(void)"_L1;
m_refreshInitialization += varName ;
m_refreshInitialization += language::eol;
} else if (language::language() == Language::Python) {
// output a 'pass' to have an empty function
m_refreshInitialization += m_indent;
- m_refreshInitialization += QLatin1String("pass");
+ m_refreshInitialization += "pass"_L1;
m_refreshInitialization += language::eol;
}
}
@@ -606,7 +610,7 @@ void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWid
const auto &attributes = page->elementAttribute();
if (!attributes.empty()) {
for (const DomProperty *p : attributes) {
- if (p->attributeName() == QLatin1String("pageId")) {
+ if (p->attributeName() == "pageId"_L1) {
if (const DomString *ds = p->elementString())
id = ds->text();
break;
@@ -624,7 +628,7 @@ void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWid
void WriteInitialization::acceptWidget(DomWidget *node)
{
- m_layoutMarginType = m_widgetChain.count() == 1 ? TopLevelMargin : ChildMargin;
+ m_layoutMarginType = m_widgetChain.size() == 1 ? TopLevelMargin : ChildMargin;
const QString className = node->attributeClass();
const QString varName = m_driver->findOrInsertWidget(node);
@@ -674,10 +678,10 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_layoutChain.push(nullptr);
m_layoutWidget = false;
- if (className == QLatin1String("QWidget") && !node->hasAttributeNative()) {
+ if (className == "QWidget"_L1 && !node->hasAttributeNative()) {
if (const DomWidget* parentWidget = m_widgetChain.top()) {
const QString parentClass = parentWidget->attributeClass();
- if (parentClass != QLatin1String("QMainWindow")
+ if (parentClass != "QMainWindow"_L1
&& !m_uic->customWidgetsInfo()->isCustomWidgetContainer(parentClass)
&& !m_uic->isContainer(parentClass))
m_layoutWidget = true;
@@ -692,7 +696,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
const DomPropertyMap attributes = propertyMap(node->elementAttribute());
- const QString pageDefaultString = QLatin1String("Page");
+ const QString pageDefaultString = u"Page"_s;
if (cwi->extends(parentClass, "QMainWindow")) {
if (cwi->extends(className, "QMenuBar")) {
@@ -703,8 +707,8 @@ void WriteInitialization::acceptWidget(DomWidget *node)
<< language::enumValue(toolBarAreaStringFromDOMAttributes(attributes)) << varName
<< ')' << language::eol;
- if (const DomProperty *pbreak = attributes.value(QLatin1String("toolBarBreak"))) {
- if (pbreak->elementBool() == QLatin1String("true")) {
+ if (const DomProperty *pbreak = attributes.value("toolBarBreak"_L1)) {
+ if (pbreak->elementBool() == "true"_L1) {
m_output << m_indent << parentWidget << language::derefPointer
<< "insertToolBarBreak(" << varName << ')' << language::eol;
}
@@ -712,9 +716,9 @@ void WriteInitialization::acceptWidget(DomWidget *node)
} else if (cwi->extends(className, "QDockWidget")) {
m_output << m_indent << parentWidget << language::derefPointer << "addDockWidget(";
- if (DomProperty *pstyle = attributes.value(QLatin1String("dockWidgetArea"))) {
- m_output << "Qt" << language::qualifier
- << language::dockWidgetArea(pstyle->elementNumber()) << ", ";
+ if (DomProperty *pstyle = attributes.value("dockWidgetArea"_L1)) {
+ QString a = expandDockWidgetArea(language::dockWidgetArea(pstyle->elementNumber()));
+ m_output << language::enumValue(a) << ", ";
}
m_output << varName << ")" << language::eol;
} else if (m_uic->customWidgetsInfo()->extends(className, "QStatusBar")) {
@@ -736,11 +740,11 @@ void WriteInitialization::acceptWidget(DomWidget *node)
} else if (m_uic->customWidgetsInfo()->extends(parentClass, "QWizard")) {
addWizardPage(varName, node, parentWidget);
} else if (m_uic->customWidgetsInfo()->extends(parentClass, "QToolBox")) {
- const DomProperty *plabel = attributes.value(QLatin1String("label"));
+ const DomProperty *plabel = attributes.value("label"_L1);
DomString *plabelString = plabel ? plabel->elementString() : nullptr;
QString icon;
- if (const DomProperty *picon = attributes.value(QLatin1String("icon")))
- icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition
+ if (const DomProperty *picon = attributes.value("icon"_L1))
+ icon = ", "_L1 + iconCall(picon); // Side effect: Writes icon definition
m_output << m_indent << parentWidget << language::derefPointer << "addItem("
<< varName << icon << ", " << noTrCall(plabelString, pageDefaultString)
<< ')' << language::eol;
@@ -750,7 +754,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
<< language::derefPointer << "indexOf(" << varName << "), "
<< autoTrCall(plabelString, pageDefaultString) << ')' << language::eol;
- if (DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) {
+ if (DomProperty *ptoolTip = attributes.value("toolTip"_L1)) {
autoTrOutput(ptoolTip->elementString())
<< language::openQtConfig(toolTipConfigKey())
<< m_indent << parentWidget << language::derefPointer << "setItemToolTip(" << parentWidget
@@ -759,11 +763,11 @@ void WriteInitialization::acceptWidget(DomWidget *node)
<< language::closeQtConfig(toolTipConfigKey());
}
} else if (m_uic->customWidgetsInfo()->extends(parentClass, "QTabWidget")) {
- const DomProperty *ptitle = attributes.value(QLatin1String("title"));
+ const DomProperty *ptitle = attributes.value("title"_L1);
DomString *ptitleString = ptitle ? ptitle->elementString() : nullptr;
QString icon;
- if (const DomProperty *picon = attributes.value(QLatin1String("icon")))
- icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition
+ if (const DomProperty *picon = attributes.value("icon"_L1))
+ icon = ", "_L1 + iconCall(picon); // Side effect: Writes icon definition
m_output << m_indent << parentWidget << language::derefPointer << "addTab("
<< varName << icon << ", " << language::emptyString << ')' << language::eol;
@@ -772,7 +776,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
<< language::derefPointer << "indexOf(" << varName << "), "
<< autoTrCall(ptitleString, pageDefaultString) << ')' << language::eol;
- if (const DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) {
+ if (const DomProperty *ptoolTip = attributes.value("toolTip"_L1)) {
autoTrOutput(ptoolTip->elementString())
<< language::openQtConfig(toolTipConfigKey())
<< m_indent << parentWidget << language::derefPointer << "setTabToolTip("
@@ -780,7 +784,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
<< "), " << autoTrCall(ptoolTip->elementString()) << ')' << language::eol
<< language::closeQtConfig(toolTipConfigKey());
}
- if (const DomProperty *pwhatsThis = attributes.value(QLatin1String("whatsThis"))) {
+ if (const DomProperty *pwhatsThis = attributes.value("whatsThis"_L1)) {
autoTrOutput(pwhatsThis->elementString())
<< language::openQtConfig(whatsThisConfigKey())
<< m_indent << parentWidget << language::derefPointer << "setTabWhatsThis("
@@ -793,41 +797,41 @@ void WriteInitialization::acceptWidget(DomWidget *node)
//
// Special handling for qtableview/qtreeview fake header attributes
//
- static const QLatin1String realPropertyNames[] = {
- QLatin1String("visible"),
- QLatin1String("cascadingSectionResizes"),
- QLatin1String("minimumSectionSize"), // before defaultSectionSize
- QLatin1String("defaultSectionSize"),
- QLatin1String("highlightSections"),
- QLatin1String("showSortIndicator"),
- QLatin1String("stretchLastSection"),
+ static const QLatin1StringView realPropertyNames[] = {
+ "visible"_L1,
+ "cascadingSectionResizes"_L1,
+ "minimumSectionSize"_L1, // before defaultSectionSize
+ "defaultSectionSize"_L1,
+ "highlightSections"_L1,
+ "showSortIndicator"_L1,
+ "stretchLastSection"_L1,
};
static const QStringList trees = {
- QLatin1String("QTreeView"), QLatin1String("QTreeWidget")
+ u"QTreeView"_s, u"QTreeWidget"_s
};
static const QStringList tables = {
- QLatin1String("QTableView"), QLatin1String("QTableWidget")
+ u"QTableView"_s, u"QTableWidget"_s
};
if (cwi->extendsOneOf(className, trees)) {
DomPropertyList headerProperties;
for (auto realPropertyName : realPropertyNames) {
- const QString fakePropertyName = QLatin1String("header")
+ const QString fakePropertyName = "header"_L1
+ QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1);
if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) {
fakeProperty->setAttributeName(realPropertyName);
headerProperties << fakeProperty;
}
}
- writeProperties(varName + language::derefPointer + QLatin1String("header()"),
- QLatin1String("QHeaderView"), headerProperties,
+ writeProperties(varName + language::derefPointer + "header()"_L1,
+ "QHeaderView"_L1, headerProperties,
WritePropertyIgnoreObjectName);
} else if (cwi->extendsOneOf(className, tables)) {
- static const QLatin1String headerPrefixes[] = {
- QLatin1String("horizontalHeader"),
- QLatin1String("verticalHeader"),
+ static const QLatin1StringView headerPrefixes[] = {
+ "horizontalHeader"_L1,
+ "verticalHeader"_L1,
};
for (auto headerPrefix : headerPrefixes) {
@@ -841,8 +845,8 @@ void WriteInitialization::acceptWidget(DomWidget *node)
}
}
const QString headerVar = varName + language::derefPointer
- + headerPrefix + QLatin1String("()");
- writeProperties(headerVar, QLatin1String("QHeaderView"),
+ + headerPrefix + "()"_L1;
+ writeProperties(headerVar, "QHeaderView"_L1,
headerProperties, WritePropertyIgnoreObjectName);
}
}
@@ -868,7 +872,7 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr
{
const DomPropertyMap attributes = propertyMap(buttonNode->elementAttribute());
// Look up the button group name as specified in the attribute and find the uniquified name
- const DomProperty *prop = attributes.value(QLatin1String("buttonGroup"));
+ const DomProperty *prop = attributes.value("buttonGroup"_L1);
if (!prop)
return;
const QString attributeName = toString(prop->elementString());
@@ -887,7 +891,7 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr
const QString groupName = m_driver->findOrInsertButtonGroup(group);
// Create on demand
if (!m_buttonGroups.contains(groupName)) {
- const QString className = QLatin1String("QButtonGroup");
+ const QString className = u"QButtonGroup"_s;
m_output << m_indent;
if (createGroupOnTheFly)
m_output << className << " *";
@@ -906,7 +910,7 @@ void WriteInitialization::acceptLayout(DomLayout *node)
const QString varName = m_driver->findOrInsertLayout(node);
const DomPropertyMap properties = propertyMap(node->elementProperty());
- const bool oldLayoutProperties = properties.value(QLatin1String("margin")) != nullptr;
+ const bool oldLayoutProperties = properties.value("margin"_L1) != nullptr;
bool isGroupBox = false;
@@ -933,36 +937,36 @@ void WriteInitialization::acceptLayout(DomLayout *node)
left = top = right = bottom = false;
for (const DomProperty *p : propList) {
const QString propertyName = p->attributeName();
- if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number)
+ if (propertyName == "leftMargin"_L1 && p->kind() == DomProperty::Number)
left = true;
- else if (propertyName == QLatin1String("topMargin") && p->kind() == DomProperty::Number)
+ else if (propertyName == "topMargin"_L1 && p->kind() == DomProperty::Number)
top = true;
- else if (propertyName == QLatin1String("rightMargin") && p->kind() == DomProperty::Number)
+ else if (propertyName == "rightMargin"_L1 && p->kind() == DomProperty::Number)
right = true;
- else if (propertyName == QLatin1String("bottomMargin") && p->kind() == DomProperty::Number)
+ else if (propertyName == "bottomMargin"_L1 && p->kind() == DomProperty::Number)
bottom = true;
}
if (!left) {
DomProperty *p = new DomProperty();
- p->setAttributeName(QLatin1String("leftMargin"));
+ p->setAttributeName("leftMargin"_L1);
p->setElementNumber(0);
newPropList.append(p);
}
if (!top) {
DomProperty *p = new DomProperty();
- p->setAttributeName(QLatin1String("topMargin"));
+ p->setAttributeName("topMargin"_L1);
p->setElementNumber(0);
newPropList.append(p);
}
if (!right) {
DomProperty *p = new DomProperty();
- p->setAttributeName(QLatin1String("rightMargin"));
+ p->setAttributeName("rightMargin"_L1);
p->setElementNumber(0);
newPropList.append(p);
}
if (!bottom) {
DomProperty *p = new DomProperty();
- p->setAttributeName(QLatin1String("bottomMargin"));
+ p->setAttributeName("bottomMargin"_L1);
p->setElementNumber(0);
newPropList.append(p);
}
@@ -983,12 +987,12 @@ void WriteInitialization::acceptLayout(DomLayout *node)
m_layoutChain.pop();
// Stretch? (Unless we are compiling for UIC3)
- const QString numberNull = QString(QLatin1Char('0'));
- writePropertyList(varName, QLatin1String("setStretch"), node->attributeStretch(), numberNull);
- writePropertyList(varName, QLatin1String("setRowStretch"), node->attributeRowStretch(), numberNull);
- writePropertyList(varName, QLatin1String("setColumnStretch"), node->attributeColumnStretch(), numberNull);
- writePropertyList(varName, QLatin1String("setColumnMinimumWidth"), node->attributeColumnMinimumWidth(), numberNull);
- writePropertyList(varName, QLatin1String("setRowMinimumHeight"), node->attributeRowMinimumHeight(), numberNull);
+ const QString numberNull(u'0');
+ writePropertyList(varName, "setStretch"_L1, node->attributeStretch(), numberNull);
+ writePropertyList(varName, "setRowStretch"_L1, node->attributeRowStretch(), numberNull);
+ writePropertyList(varName, "setColumnStretch"_L1, node->attributeColumnStretch(), numberNull);
+ writePropertyList(varName, "setColumnMinimumWidth"_L1, node->attributeColumnMinimumWidth(), numberNull);
+ writePropertyList(varName, "setRowMinimumHeight"_L1, node->attributeRowMinimumHeight(), numberNull);
}
// Apply a comma-separated list of values using a function "setSomething(int idx, value)"
@@ -999,8 +1003,8 @@ void WriteInitialization::writePropertyList(const QString &varName,
{
if (value.isEmpty())
return;
- const QStringList list = value.split(QLatin1Char(','));
- const int count = list.count();
+ const QStringList list = value.split(u',');
+ const int count = list.size();
for (int i = 0; i < count; i++) {
if (list.at(i) != defaultValue) {
m_output << m_indent << varName << language::derefPointer << setFunction
@@ -1019,21 +1023,20 @@ void WriteInitialization::acceptSpacer(DomSpacer *node)
static inline QString formLayoutRole(int column, int colspan)
{
if (colspan > 1)
- return QLatin1String("QFormLayout::SpanningRole");
- return column == 0 ? QLatin1String("QFormLayout::LabelRole") : QLatin1String("QFormLayout::FieldRole");
+ return "QFormLayout::SpanningRole"_L1;
+ return column == 0 ? "QFormLayout::LabelRole"_L1 : "QFormLayout::FieldRole"_L1;
}
static QString layoutAddMethod(DomLayoutItem::Kind kind, const QString &layoutClass)
{
- const QString methodPrefix = layoutClass == QLatin1String("QFormLayout")
- ? QLatin1String("set") : QLatin1String("add");
+ const auto methodPrefix = layoutClass == "QFormLayout"_L1 ? "set"_L1 : "add"_L1;
switch (kind) {
case DomLayoutItem::Widget:
- return methodPrefix + QLatin1String("Widget");
+ return methodPrefix + "Widget"_L1;
case DomLayoutItem::Layout:
- return methodPrefix + QLatin1String("Layout");
+ return methodPrefix + "Layout"_L1;
case DomLayoutItem::Spacer:
- return methodPrefix + QLatin1String("Item");
+ return methodPrefix + "Item"_L1;
case DomLayoutItem::Unknown:
Q_ASSERT( false );
break;
@@ -1056,7 +1059,7 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node)
m_output << "\n" << m_indent << layoutName << language::derefPointer << ""
<< layoutAddMethod(node->kind(), layout->attributeClass()) << '(';
- if (layout->attributeClass() == QLatin1String("QGridLayout")) {
+ if (layout->attributeClass() == "QGridLayout"_L1) {
const int row = node->attributeRow();
const int col = node->attributeColumn();
@@ -1065,14 +1068,14 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node)
m_output << itemName << ", " << row << ", " << col << ", " << rowSpan << ", " << colSpan;
if (!node->attributeAlignment().isEmpty())
m_output << ", " << language::enumValue(node->attributeAlignment());
- } else if (layout->attributeClass() == QLatin1String("QFormLayout")) {
+ } else if (layout->attributeClass() == "QFormLayout"_L1) {
const int row = node->attributeRow();
const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
const QString role = formLayoutRole(node->attributeColumn(), colSpan);
m_output << row << ", " << language::enumValue(role) << ", " << itemName;
} else {
m_output << itemName;
- if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty())
+ if (layout->attributeClass().contains("Box"_L1) && !node->attributeAlignment().isEmpty())
m_output << ", 0, " << language::enumValue(node->attributeAlignment());
}
m_output << ")" << language::eol << "\n";
@@ -1088,7 +1091,7 @@ void WriteInitialization::acceptActionGroup(DomActionGroup *node)
m_output << m_indent << actionName << " = " << language::operatorNew
<< "QActionGroup(" << varName << ")" << language::eol;
- writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty());
+ writeProperties(actionName, "QActionGroup"_L1, node->elementProperty());
m_actionGroupChain.push(node);
TreeWalker::acceptActionGroup(node);
@@ -1108,7 +1111,7 @@ void WriteInitialization::acceptAction(DomAction *node)
m_output << m_indent << actionName << " = " << language::operatorNew
<< "QAction(" << varName << ')' << language::eol;
- writeProperties(actionName, QLatin1String("QAction"), node->elementProperty());
+ writeProperties(actionName, "QAction"_L1, node->elementProperty());
}
void WriteInitialization::acceptActionRef(DomActionRef *node)
@@ -1121,7 +1124,7 @@ void WriteInitialization::acceptActionRef(DomActionRef *node)
const QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
- if (m_widgetChain.top() && actionName == QLatin1String("separator")) {
+ if (m_widgetChain.top() && actionName == "separator"_L1) {
// separator is always reserved!
m_actionOut << m_indent << varName << language::derefPointer
<< "addSeparator()" << language::eol;
@@ -1152,35 +1155,50 @@ QString WriteInitialization::writeStringListProperty(const DomStringList *list)
{
QString propertyValue;
QTextStream str(&propertyValue);
- str << "QStringList()";
+ char trailingDelimiter = '}';
+ switch (language::language()) {
+ case Language::Cpp:
+ str << "QStringList{";
+ break;
+ case Language::Python:
+ str << '[';
+ trailingDelimiter = ']';
+ break;
+ }
const QStringList values = list->elementString();
- if (values.isEmpty())
- return propertyValue;
- if (needsTranslation(list)) {
- const QString comment = list->attributeComment();
- for (int i = 0; i < values.size(); ++i)
- str << '\n' << m_indent << " << " << trCall(values.at(i), comment);
- } else {
- for (int i = 0; i < values.size(); ++i)
- str << " << " << language::qstring(values.at(i), m_dindent);
+ if (!values.isEmpty()) {
+ if (needsTranslation(list)) {
+ const QString comment = list->attributeComment();
+ const qsizetype last = values.size() - 1;
+ for (qsizetype i = 0; i <= last; ++i) {
+ str << '\n' << m_indent << " " << trCall(values.at(i), comment);
+ if (i != last)
+ str << ',';
+ }
+ } else {
+ for (qsizetype i = 0; i < values.size(); ++i) {
+ if (i)
+ str << ", ";
+ str << language::qstring(values.at(i), m_dindent);
+ }
+ }
}
+ str << trailingDelimiter;
return propertyValue;
}
static QString configKeyForProperty(const QString &propertyName)
{
- if (propertyName == QLatin1String("toolTip"))
+ if (propertyName == "toolTip"_L1)
return toolTipConfigKey();
- if (propertyName == QLatin1String("whatsThis"))
+ if (propertyName == "whatsThis"_L1)
return whatsThisConfigKey();
- if (propertyName == QLatin1String("statusTip"))
+ if (propertyName == "statusTip"_L1)
return statusTipConfigKey();
- if (propertyName == QLatin1String("shortcut"))
+ if (propertyName == "shortcut"_L1)
return shortcutConfigKey();
- if (propertyName == QLatin1String("accessibleName")
- || propertyName == QLatin1String("accessibleDescription")) {
+ if (propertyName == "accessibleName"_L1 || propertyName == "accessibleDescription"_L1)
return accessibilityConfigKey();
- }
return QString();
}
@@ -1189,11 +1207,11 @@ void WriteInitialization::writeProperties(const QString &varName,
const DomPropertyList &lst,
unsigned flags)
{
- const bool isTopLevel = m_widgetChain.count() == 1;
+ const bool isTopLevel = m_widgetChain.size() == 1;
if (m_uic->customWidgetsInfo()->extends(className, "QAxWidget")) {
DomPropertyMap properties = propertyMap(lst);
- if (DomProperty *p = properties.value(QLatin1String("control"))) {
+ if (DomProperty *p = properties.value("control"_L1)) {
m_output << m_indent << varName << language::derefPointer << "setControl("
<< language::qstring(toString(p->elementString()), m_dindent)
<< ')' << language::eol;
@@ -1218,7 +1236,7 @@ void WriteInitialization::writeProperties(const QString &varName,
objectName.remove(0, language::self.size());
m_output << m_indent << indent
<< varName << language::derefPointer << "setObjectName("
- << language::qstring(objectName, m_dindent) << ')' << language::eol;
+ << language::charliteral(objectName, m_dindent) << ')' << language::eol;
}
int leftMargin, topMargin, rightMargin, bottomMargin;
@@ -1233,58 +1251,58 @@ void WriteInitialization::writeProperties(const QString &varName,
bool delayProperty = false;
// special case for the property `geometry': Do not use position
- if (isTopLevel && propertyName == QLatin1String("geometry") && p->elementRect()) {
+ if (isTopLevel && propertyName == "geometry"_L1 && p->elementRect()) {
const DomRect *r = p->elementRect();
m_output << m_indent << varName << language::derefPointer << "resize("
<< r->elementWidth() << ", " << r->elementHeight() << ')' << language::eol;
continue;
}
- if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow
+ if (propertyName == "currentRow"_L1 // QListWidget::currentRow
&& m_uic->customWidgetsInfo()->extends(className, "QListWidget")) {
m_delayedOut << m_indent << varName << language::derefPointer
<< "setCurrentRow(" << p->elementNumber() << ')' << language::eol;
continue;
}
static const QStringList currentIndexWidgets = {
- QLatin1String("QComboBox"), QLatin1String("QStackedWidget"),
- QLatin1String("QTabWidget"), QLatin1String("QToolBox")
+ u"QComboBox"_s, u"QStackedWidget"_s,
+ u"QTabWidget"_s, u"QToolBox"_s
};
- if (propertyName == QLatin1String("currentIndex") // set currentIndex later
+ if (propertyName == "currentIndex"_L1 // set currentIndex later
&& (m_uic->customWidgetsInfo()->extendsOneOf(className, currentIndexWidgets))) {
m_delayedOut << m_indent << varName << language::derefPointer
<< "setCurrentIndex(" << p->elementNumber() << ')' << language::eol;
continue;
}
- if (propertyName == QLatin1String("tabSpacing")
+ if (propertyName == "tabSpacing"_L1
&& m_uic->customWidgetsInfo()->extends(className, "QToolBox")) {
m_delayedOut << m_indent << varName << language::derefPointer
<< "layout()" << language::derefPointer << "setSpacing("
<< p->elementNumber() << ')' << language::eol;
continue;
}
- if (propertyName == QLatin1String("control") // ActiveQt support
+ if (propertyName == "control"_L1 // ActiveQt support
&& m_uic->customWidgetsInfo()->extends(className, "QAxWidget")) {
// already done ;)
continue;
}
- if (propertyName == QLatin1String("default")
+ if (propertyName == "default"_L1
&& m_uic->customWidgetsInfo()->extends(className, "QPushButton")) {
// QTBUG-44406: Setting of QPushButton::default needs to be delayed until the parent is set
delayProperty = true;
- } else if (propertyName == QLatin1String("database")
+ } else if (propertyName == "database"_L1
&& p->elementStringList()) {
// Sql support
continue;
- } else if (propertyName == QLatin1String("frameworkCode")
+ } else if (propertyName == "frameworkCode"_L1
&& p->kind() == DomProperty::Bool) {
// Sql support
continue;
- } else if (propertyName == QLatin1String("orientation")
+ } else if (propertyName == "orientation"_L1
&& m_uic->customWidgetsInfo()->extends(className, "Line")) {
// Line support
- QString shape = QLatin1String("QFrame::HLine");
- if (p->elementEnum() == QLatin1String("Qt::Vertical"))
- shape = QLatin1String("QFrame::VLine");
+ QString shape = u"QFrame::Shape::HLine"_s;
+ if (p->elementEnum().endsWith("::Vertical"_L1))
+ shape = u"QFrame::Shape::VLine"_s;
m_output << m_indent << varName << language::derefPointer << "setFrameShape("
<< language::enumValue(shape) << ')' << language::eol;
@@ -1292,32 +1310,32 @@ void WriteInitialization::writeProperties(const QString &varName,
if (!frameShadowEncountered) {
m_output << m_indent << varName << language::derefPointer
<< "setFrameShadow("
- << language::enumValue(QLatin1String("QFrame::Sunken"))
+ << language::enumValue("QFrame::Shadow::Sunken"_L1)
<< ')' << language::eol;
}
continue;
- } else if ((flags & WritePropertyIgnoreMargin) && propertyName == QLatin1String("margin")) {
+ } else if ((flags & WritePropertyIgnoreMargin) && propertyName == "margin"_L1) {
continue;
- } else if ((flags & WritePropertyIgnoreSpacing) && propertyName == QLatin1String("spacing")) {
+ } else if ((flags & WritePropertyIgnoreSpacing) && propertyName == "spacing"_L1) {
continue;
- } else if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number) {
+ } else if (propertyName == "leftMargin"_L1 && p->kind() == DomProperty::Number) {
leftMargin = p->elementNumber();
continue;
- } else if (propertyName == QLatin1String("topMargin") && p->kind() == DomProperty::Number) {
+ } else if (propertyName == "topMargin"_L1 && p->kind() == DomProperty::Number) {
topMargin = p->elementNumber();
continue;
- } else if (propertyName == QLatin1String("rightMargin") && p->kind() == DomProperty::Number) {
+ } else if (propertyName == "rightMargin"_L1 && p->kind() == DomProperty::Number) {
rightMargin = p->elementNumber();
continue;
- } else if (propertyName == QLatin1String("bottomMargin") && p->kind() == DomProperty::Number) {
+ } else if (propertyName == "bottomMargin"_L1 && p->kind() == DomProperty::Number) {
bottomMargin = p->elementNumber();
continue;
- } else if (propertyName == QLatin1String("numDigits") // Deprecated in Qt 4, removed in Qt 5.
+ } else if (propertyName == "numDigits"_L1 // Deprecated in Qt 4, removed in Qt 5.
&& m_uic->customWidgetsInfo()->extends(className, "QLCDNumber")) {
qWarning("Widget '%s': Deprecated property QLCDNumber::numDigits encountered. It has been replaced by QLCDNumber::digitCount.",
qPrintable(varName));
- propertyName = QLatin1String("digitCount");
- } else if (propertyName == QLatin1String("frameShadow")) {
+ propertyName = "digitCount"_L1;
+ } else if (propertyName == "frameShadow"_L1) {
frameShadowEncountered = true;
}
@@ -1333,7 +1351,7 @@ void WriteInitialization::writeProperties(const QString &varName,
str << language::derefPointer <<"set" << propertyName.at(0).toUpper()
<< QStringView{propertyName}.mid(1) << '(';
} else {
- str << language::derefPointer << QLatin1String("setProperty(\"")
+ str << language::derefPointer << "setProperty(\""_L1
<< propertyName << "\", ";
if (language::language() == Language::Cpp) {
str << "QVariant";
@@ -1355,15 +1373,16 @@ void WriteInitialization::writeProperties(const QString &varName,
propertyValue = domColor2QString(p->elementColor());
break;
case DomProperty::Cstring:
- if (propertyName == QLatin1String("buddy") && m_uic->customWidgetsInfo()->extends(className, "QLabel")) {
+ if (propertyName == "buddy"_L1 && m_uic->customWidgetsInfo()->extends(className, "QLabel")) {
Buddy buddy = { varName, p->elementCstring() };
m_buddies.append(std::move(buddy));
} else {
+ const bool useQByteArray = !stdset && language::language() == Language::Cpp;
QTextStream str(&propertyValue);
- if (!stdset)
+ if (useQByteArray)
str << "QByteArray(";
str << language::charliteral(p->elementCstring(), m_dindent);
- if (!stdset)
+ if (useQByteArray)
str << ')';
}
break;
@@ -1373,9 +1392,9 @@ void WriteInitialization::writeProperties(const QString &varName,
break;
case DomProperty::CursorShape:
if (p->hasAttributeStdset() && !p->attributeStdset())
- varNewName += language::derefPointer + QLatin1String("viewport()");
- propertyValue = QLatin1String("QCursor(Qt") + language::qualifier
- + p->elementCursorShape() + QLatin1Char(')');
+ varNewName += language::derefPointer + "viewport()"_L1;
+ propertyValue = "QCursor(Qt"_L1 + language::qualifier + "CursorShape"_L1
+ + language::qualifier + p->elementCursorShape() + u')';
break;
case DomProperty::Enum:
propertyValue = p->elementEnum();
@@ -1398,12 +1417,12 @@ void WriteInitialization::writeProperties(const QString &varName,
break;
case DomProperty::Palette: {
const DomPalette *pal = p->elementPalette();
- const QString paletteName = m_driver->unique(QLatin1String("palette"));
+ const QString paletteName = m_driver->unique("palette"_L1);
m_output << m_indent << language::stackVariable("QPalette", paletteName)
<< language::eol;
- writeColorGroup(pal->elementActive(), QLatin1String("QPalette::Active"), paletteName);
- writeColorGroup(pal->elementInactive(), QLatin1String("QPalette::Inactive"), paletteName);
- writeColorGroup(pal->elementDisabled(), QLatin1String("QPalette::Disabled"), paletteName);
+ writeColorGroup(pal->elementActive(), "QPalette::Active"_L1, paletteName);
+ writeColorGroup(pal->elementInactive(), "QPalette::Inactive"_L1, paletteName);
+ writeColorGroup(pal->elementDisabled(), "QPalette::Disabled"_L1, paletteName);
propertyValue = paletteName;
break;
@@ -1463,7 +1482,7 @@ void WriteInitialization::writeProperties(const QString &varName,
break;
}
case DomProperty::String: {
- if (propertyName == QLatin1String("objectName")) {
+ if (propertyName == "objectName"_L1) {
const QString v = p->elementString()->text();
if (v == varName)
break;
@@ -1479,17 +1498,17 @@ void WriteInitialization::writeProperties(const QString &varName,
break;
case DomProperty::UInt:
propertyValue = QString::number(p->elementUInt());
- propertyValue += QLatin1Char('u');
+ propertyValue += u'u';
break;
case DomProperty::LongLong:
- propertyValue = QLatin1String("Q_INT64_C(");
+ propertyValue = "Q_INT64_C("_L1;
propertyValue += QString::number(p->elementLongLong());
- propertyValue += QLatin1Char(')');;
+ propertyValue += u')';
break;
case DomProperty::ULongLong:
- propertyValue = QLatin1String("Q_UINT64_C(");
+ propertyValue = "Q_UINT64_C("_L1;
propertyValue += QString::number(p->elementULongLong());
- propertyValue += QLatin1Char(')');
+ propertyValue += u')';
break;
case DomProperty::Float:
propertyValue = QString::number(p->elementFloat(), 'f', 8);
@@ -1587,16 +1606,22 @@ QString WriteInitialization::writeSizePolicy(const DomSizePolicy *sp)
// insert with new name
- const QString spName = m_driver->unique(QLatin1String("sizePolicy"));
+ const QString spName = m_driver->unique("sizePolicy"_L1);
m_sizePolicyNameMap.insert(sizePolicyHandle, spName);
m_output << m_indent << language::stackVariableWithInitParameters("QSizePolicy", spName);
+ QString horizPolicy;
+ QString vertPolicy;
if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) {
- m_output << "QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementHSizeType())
- << ", QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementVSizeType());
+ horizPolicy = language::sizePolicy(sp->elementHSizeType());
+ vertPolicy = language::sizePolicy(sp->elementVSizeType());
} else if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
- m_output << "QSizePolicy" << language::qualifier << sp->attributeHSizeType()
- << ", QSizePolicy" << language::qualifier << sp->attributeVSizeType();
+ horizPolicy = sp->attributeHSizeType();
+ vertPolicy = sp->attributeVSizeType();
+ }
+ if (!horizPolicy.isEmpty() && !vertPolicy.isEmpty()) {
+ m_output << language::enumValue(expandSizePolicyEnum(horizPolicy))
+ << ", " << language::enumValue(expandSizePolicyEnum(vertPolicy));
}
m_output << ')' << language::eol;
@@ -1619,7 +1644,7 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
}
// insert with new name
- const QString fontName = m_driver->unique(QLatin1String("font"));
+ const QString fontName = m_driver->unique("font"_L1);
m_fontPropertiesNameMap.insert(FontHandle(f), fontName);
m_output << m_indent << language::stackVariable("QFont", fontName)
@@ -1635,10 +1660,14 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
<< ")" << language::eol;
}
- if (f->hasElementBold()) {
+ if (f->hasElementFontWeight()) {
+ m_output << m_indent << fontName << ".setWeight(QFont"
+ << language::qualifier << f->elementFontWeight() << ')' << language::eol;
+ } else if (f->hasElementBold()) {
m_output << m_indent << fontName << ".setBold("
<< language::boolValue(f->elementBold()) << ')' << language::eol;
}
+
if (f->hasElementItalic()) {
m_output << m_indent << fontName << ".setItalic("
<< language::boolValue(f->elementItalic()) << ')' << language::eol;
@@ -1665,6 +1694,11 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
m_output << m_indent << fontName << ".setStyleStrategy(QFont"
<< language::qualifier << f->elementStyleStrategy() << ')' << language::eol;
}
+ if (f->hasElementHintingPreference()) {
+ m_output << m_indent << fontName << ".setHintingPreference(QFont"
+ << language::qualifier << f->elementHintingPreference() << ')' << language::eol;
+ }
+
return fontName;
}
@@ -1674,8 +1708,9 @@ static void writeIconAddFile(QTextStream &output, const QString &indent,
{
output << indent << iconName << ".addFile("
<< language::qstring(fileName, indent) << ", QSize(), QIcon"
- << language::qualifier << mode << ", QIcon" << language::qualifier
- << state << ')' << language::eol;
+ << language::qualifier << "Mode" << language::qualifier << mode
+ << ", QIcon" << language::qualifier << "State" << language::qualifier << state
+ << ')' << language::eol;
}
// Post 4.4 write resource icon
@@ -1723,7 +1758,8 @@ static void writeIconAddPixmap(QTextStream &output, const QString &indent,
const char *mode, const char *state)
{
output << indent << iconName << ".addPixmap(" << call << ", QIcon"
- << language::qualifier << mode << ", QIcon" << language::qualifier
+ << language::qualifier << "Mode" << language::qualifier << mode
+ << ", QIcon" << language::qualifier << "State" << language::qualifier
<< state << ')' << language::eol;
}
@@ -1734,46 +1770,99 @@ void WriteInitialization::writePixmapFunctionIcon(QTextStream &output,
{
if (i->hasElementNormalOff()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text()),
+ pixCall("QPixmap"_L1, i->elementNormalOff()->text()),
"Normal", "Off");
}
if (i->hasElementNormalOn()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text()),
+ pixCall("QPixmap"_L1, i->elementNormalOn()->text()),
"Normal", "On");
}
if (i->hasElementDisabledOff()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text()),
+ pixCall("QPixmap"_L1, i->elementDisabledOff()->text()),
"Disabled", "Off");
}
if (i->hasElementDisabledOn()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text()),
+ pixCall("QPixmap"_L1, i->elementDisabledOn()->text()),
"Disabled", "On");
}
if (i->hasElementActiveOff()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text()),
+ pixCall("QPixmap"_L1, i->elementActiveOff()->text()),
"Active", "Off");
}
if (i->hasElementActiveOn()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text()),
+ pixCall("QPixmap"_L1, i->elementActiveOn()->text()),
"Active", "On");
}
if (i->hasElementSelectedOff()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text()),
+ pixCall("QPixmap"_L1, i->elementSelectedOff()->text()),
"Selected", "Off");
}
if (i->hasElementSelectedOn()) {
writeIconAddPixmap(output, indent, iconName,
- pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text()),
+ pixCall("QPixmap"_L1, i->elementSelectedOn()->text()),
"Selected", "On");
}
}
+// Write QIcon::fromTheme() (value from enum or variable)
+struct iconFromTheme
+{
+ explicit iconFromTheme(const QString &theme) : m_theme(theme) {}
+
+ QString m_theme;
+};
+
+QTextStream &operator<<(QTextStream &str, const iconFromTheme &i)
+{
+ str << "QIcon" << language::qualifier << "fromTheme(" << i.m_theme << ')';
+ return str;
+}
+
+// Write QIcon::fromTheme() for an XDG icon from string literal
+struct iconFromThemeStringLiteral
+{
+ explicit iconFromThemeStringLiteral(const QString &theme) : m_theme(theme) {}
+
+ QString m_theme;
+};
+
+QTextStream &operator<<(QTextStream &str, const iconFromThemeStringLiteral &i)
+{
+ str << "QIcon" << language::qualifier << "fromTheme(" << language::qstring(i.m_theme) << ')';
+ return str;
+}
+
+// Write QIcon::fromTheme() with a path as fallback, add a check using
+// QIcon::hasThemeIcon().
+void WriteInitialization::writeThemeIconCheckAssignment(const QString &themeValue,
+ const QString &iconName,
+ const DomResourceIcon *i)
+
+{
+ const bool isCpp = language::language() == Language::Cpp;
+ m_output << m_indent << "if ";
+ if (isCpp)
+ m_output << '(';
+ m_output << "QIcon" << language::qualifier << "hasThemeIcon("
+ << themeValue << ')' << (isCpp ? ") {" : ":") << '\n'
+ << m_dindent << iconName << " = " << iconFromTheme(themeValue)
+ << language::eol;
+ m_output << m_indent << (isCpp ? "} else {" : "else:") << '\n';
+ if (m_uic->pixmapFunction().isEmpty())
+ writeResourceIcon(m_output, iconName, m_dindent, i);
+ else
+ writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
+ if (isCpp)
+ m_output << m_indent << '}';
+ m_output << '\n';
+}
+
QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
{
// check cache
@@ -1783,7 +1872,7 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
return it.value();
// insert with new name
- const QString iconName = m_driver->unique(QLatin1String("icon"));
+ const QString iconName = m_driver->unique("icon"_L1);
m_iconPropertiesNameMap.insert(IconHandle(i), iconName);
const bool isCpp = language::language() == Language::Cpp;
@@ -1792,13 +1881,14 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
m_output << m_indent;
if (isCpp)
m_output << "const QIcon ";
- m_output << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())
+ m_output << iconName << " = " << pixCall("QIcon"_L1, i->text())
<< language::eol;
return iconName;
}
// 4.4 onwards
- if (i->attributeTheme().isEmpty()) {
+ QString theme = i->attributeTheme();
+ if (theme.isEmpty()) {
// No theme: Write resource icon as is
m_output << m_indent << language::stackVariable("QIcon", iconName)
<< language::eol;
@@ -1809,12 +1899,21 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
return iconName;
}
+ const bool isThemeEnum = theme.startsWith("QIcon::"_L1);
+ if (isThemeEnum)
+ theme = language::enumValue(theme);
+
// Theme: Generate code to check the theme and default to resource
if (iconHasStatePixmaps(i)) {
// Theme + default state pixmaps:
// Generate code to check the theme and default to state pixmaps
m_output << m_indent << language::stackVariable("QIcon", iconName) << language::eol;
- const char themeNameStringVariableC[] = "iconThemeName";
+ if (isThemeEnum) {
+ writeThemeIconCheckAssignment(theme, iconName, i);
+ return iconName;
+ }
+
+ static constexpr auto themeNameStringVariableC = "iconThemeName"_L1;
// Store theme name in a variable
m_output << m_indent;
if (m_firstThemeIcon) { // Declare variable string
@@ -1823,32 +1922,19 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
m_firstThemeIcon = false;
}
m_output << themeNameStringVariableC << " = "
- << language::qstring(i->attributeTheme()) << language::eol;
- m_output << m_indent << "if ";
- if (isCpp)
- m_output << '(';
- m_output << "QIcon" << language::qualifier << "hasThemeIcon("
- << themeNameStringVariableC << ')' << (isCpp ? ") {" : ":") << '\n'
- << m_dindent << iconName << " = QIcon" << language::qualifier << "fromTheme("
- << themeNameStringVariableC << ')' << language::eol
- << m_indent << (isCpp ? "} else {" : "else:") << '\n';
- if (m_uic->pixmapFunction().isEmpty())
- writeResourceIcon(m_output, iconName, m_dindent, i);
- else
- writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
- m_output << m_indent;
- if (isCpp)
- m_output << '}';
- m_output << '\n';
+ << language::qstring(theme) << language::eol;
+ writeThemeIconCheckAssignment(themeNameStringVariableC, iconName, i);
return iconName;
}
// Theme, but no state pixmaps: Construct from theme directly.
m_output << m_indent
- << language::stackVariableWithInitParameters("QIcon", iconName)
- << "QIcon" << language::qualifier << "fromTheme("
- << language::qstring(i->attributeTheme()) << "))"
- << language::eol;
+ << language::stackVariableWithInitParameters("QIcon", iconName);
+ if (isThemeEnum)
+ m_output << iconFromTheme(theme);
+ else
+ m_output << iconFromThemeStringLiteral(theme);
+ m_output << ')' << language::eol;
return iconName;
}
@@ -1868,7 +1954,7 @@ QString WriteInitialization::domColor2QString(const DomColor *c)
static inline QVersionNumber colorRoleVersionAdded(const QString &roleName)
{
- if (roleName == QLatin1String("PlaceholderText"))
+ if (roleName == "PlaceholderText"_L1)
return QVersionNumber(5, 12, 0);
return QVersionNumber();
}
@@ -1916,7 +2002,7 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri
QString WriteInitialization::writeBrushInitialization(const DomBrush *brush)
{
// Simple solid, colored brushes are cached
- const bool solidColoredBrush = !brush->hasAttributeBrushStyle() || brush->attributeBrushStyle() == QLatin1String("SolidPattern");
+ const bool solidColoredBrush = !brush->hasAttributeBrushStyle() || brush->attributeBrushStyle() == "SolidPattern"_L1;
uint rgb = 0;
if (solidColoredBrush) {
if (const DomColor *color = brush->elementColor()) {
@@ -1930,7 +2016,7 @@ QString WriteInitialization::writeBrushInitialization(const DomBrush *brush)
}
}
// Create and enter into cache if simple
- const QString brushName = m_driver->unique(QLatin1String("brush"));
+ const QString brushName = m_driver->unique("brush"_L1);
writeBrush(brush, brushName);
if (solidColoredBrush)
m_colorBrushHash.insert(rgb, brushName);
@@ -1939,24 +2025,24 @@ QString WriteInitialization::writeBrushInitialization(const DomBrush *brush)
void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brushName)
{
- QString style = QLatin1String("SolidPattern");
+ QString style = u"SolidPattern"_s;
if (brush->hasAttributeBrushStyle())
style = brush->attributeBrushStyle();
- if (style == QLatin1String("LinearGradientPattern") ||
- style == QLatin1String("RadialGradientPattern") ||
- style == QLatin1String("ConicalGradientPattern")) {
+ if (style == "LinearGradientPattern"_L1 ||
+ style == "RadialGradientPattern"_L1 ||
+ style == "ConicalGradientPattern"_L1) {
const DomGradient *gradient = brush->elementGradient();
const QString gradientType = gradient->attributeType();
- const QString gradientName = m_driver->unique(QLatin1String("gradient"));
- if (gradientType == QLatin1String("LinearGradient")) {
+ const QString gradientName = m_driver->unique("gradient"_L1);
+ if (gradientType == "LinearGradient"_L1) {
m_output << m_indent
<< language::stackVariableWithInitParameters("QLinearGradient", gradientName)
<< gradient->attributeStartX()
<< ", " << gradient->attributeStartY()
<< ", " << gradient->attributeEndX()
<< ", " << gradient->attributeEndY() << ')' << language::eol;
- } else if (gradientType == QLatin1String("RadialGradient")) {
+ } else if (gradientType == "RadialGradient"_L1) {
m_output << m_indent
<< language::stackVariableWithInitParameters("QRadialGradient", gradientName)
<< gradient->attributeCentralX()
@@ -1964,7 +2050,7 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
<< ", " << gradient->attributeRadius()
<< ", " << gradient->attributeFocalX()
<< ", " << gradient->attributeFocalY() << ')' << language::eol;
- } else if (gradientType == QLatin1String("ConicalGradient")) {
+ } else if (gradientType == "ConicalGradient"_L1) {
m_output << m_indent
<< language::stackVariableWithInitParameters("QConicalGradient", gradientName)
<< gradient->attributeCentralX()
@@ -1992,7 +2078,7 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
m_output << m_indent
<< language::stackVariableWithInitParameters("QBrush", brushName)
<< gradientName << ')' << language::eol;
- } else if (style == QLatin1String("TexturePattern")) {
+ } else if (style == "TexturePattern"_L1) {
const DomProperty *property = brush->elementTexture();
const QString iconValue = iconCall(property);
@@ -2057,42 +2143,42 @@ QString WriteInitialization::iconCall(const DomProperty *icon)
QString WriteInitialization::pixCall(const DomProperty *p) const
{
- QString type, s;
+ QLatin1StringView type;
+ QString s;
switch (p->kind()) {
case DomProperty::IconSet:
- type = QLatin1String("QIcon");
+ type = "QIcon"_L1;
s = p->elementIconSet()->text();
break;
case DomProperty::Pixmap:
- type = QLatin1String("QPixmap");
+ type = "QPixmap"_L1;
s = p->elementPixmap()->text();
break;
default:
qWarning("%s: Warning: Unknown icon format encountered. The ui-file was generated with a too-recent version of Designer.",
qPrintable(m_option.messagePrefix()));
- return QLatin1String("QIcon()");
+ return "QIcon()"_L1;
break;
}
return pixCall(type, s);
}
-QString WriteInitialization::pixCall(const QString &t, const QString &text) const
+QString WriteInitialization::pixCall(QLatin1StringView t, const QString &text) const
{
- QString type = t;
- if (text.isEmpty()) {
- type += QLatin1String("()");
- return type;
- }
+ if (text.isEmpty())
+ return t % "()"_L1;
- QTextStream str(&type);
+ QString result;
+ QTextStream str(&result);
+ str << t;
str << '(';
- QString pixFunc = m_uic->pixmapFunction();
+ const QString pixFunc = m_uic->pixmapFunction();
if (pixFunc.isEmpty())
str << language::qstring(text, m_dindent);
else
str << pixFunc << '(' << language::charliteral(text, m_dindent) << ')';
str << ')';
- return type;
+ return result;
}
void WriteInitialization::initializeComboBox(DomWidget *w)
@@ -2107,8 +2193,8 @@ void WriteInitialization::initializeComboBox(DomWidget *w)
for (int i = 0; i < items.size(); ++i) {
const DomItem *item = items.at(i);
const DomPropertyMap properties = propertyMap(item->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *icon = properties.value(QLatin1String("icon"));
+ const DomProperty *text = properties.value("text"_L1);
+ const DomProperty *icon = properties.value("icon"_L1);
QString iconValue;
if (icon)
@@ -2135,7 +2221,7 @@ QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName
// turn off sortingEnabled to force programmatic item order (setItem())
QString tempName;
if (!w->elementItem().isEmpty()) {
- tempName = m_driver->unique(QLatin1String("__sortingEnabled"));
+ tempName = m_driver->unique("__sortingEnabled"_L1);
m_refreshOut << "\n";
m_refreshOut << m_indent;
if (language::language() == Language::Cpp)
@@ -2227,10 +2313,10 @@ void WriteInitialization::addQtFlagsInitializer(Item *item,
const DomPropertyMap &properties, const QString &name, int column) const
{
if (const DomProperty *p = properties.value(name)) {
- const QString orOperator = QLatin1Char('|') + language::qtQualifier;
+ const QString orOperator = u'|' + language::qtQualifier;
QString v = p->elementSet();
if (!v.isEmpty()) {
- v.replace(QLatin1Char('|'), orOperator);
+ v.replace(u'|', orOperator);
addInitializer(item, name, column, language::qtQualifier + v);
}
}
@@ -2256,20 +2342,20 @@ void WriteInitialization::addQtEnumInitializer(Item *item,
void WriteInitialization::addCommonInitializers(Item *item,
const DomPropertyMap &properties, int column)
{
- if (const DomProperty *icon = properties.value(QLatin1String("icon")))
- addInitializer(item, QLatin1String("icon"), column, iconCall(icon));
- addBrushInitializer(item, properties, QLatin1String("foreground"), column);
- addBrushInitializer(item, properties, QLatin1String("background"), column);
- if (const DomProperty *font = properties.value(QLatin1String("font")))
- addInitializer(item, QLatin1String("font"), column, writeFontProperties(font->elementFont()));
- addQtFlagsInitializer(item, properties, QLatin1String("textAlignment"), column);
- addQtEnumInitializer(item, properties, QLatin1String("checkState"), column);
- addStringInitializer(item, properties, QLatin1String("text"), column);
- addStringInitializer(item, properties, QLatin1String("toolTip"), column,
+ if (const DomProperty *icon = properties.value("icon"_L1))
+ addInitializer(item, "icon"_L1, column, iconCall(icon));
+ addBrushInitializer(item, properties, "foreground"_L1, column);
+ addBrushInitializer(item, properties, "background"_L1, column);
+ if (const DomProperty *font = properties.value("font"_L1))
+ addInitializer(item, "font"_L1, column, writeFontProperties(font->elementFont()));
+ addQtFlagsInitializer(item, properties, "textAlignment"_L1, column);
+ addQtEnumInitializer(item, properties, "checkState"_L1, column);
+ addStringInitializer(item, properties, "text"_L1, column);
+ addStringInitializer(item, properties, "toolTip"_L1, column,
toolTipConfigKey());
- addStringInitializer(item, properties, QLatin1String("whatsThis"), column,
+ addStringInitializer(item, properties, "whatsThis"_L1, column,
whatsThisConfigKey());
- addStringInitializer(item, properties, QLatin1String("statusTip"), column,
+ addStringInitializer(item, properties, "statusTip"_L1, column,
statusTipConfigKey());
}
@@ -2290,8 +2376,8 @@ void WriteInitialization::initializeListWidget(DomWidget *w)
const DomPropertyMap properties = propertyMap(domItem->elementProperty());
- Item item(QLatin1String("QListWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
- addQtFlagsInitializer(&item, properties, QLatin1String("flags"));
+ Item item("QListWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
+ addQtFlagsInitializer(&item, properties, "flags"_L1);
addCommonInitializers(&item, properties);
item.writeSetupUi(varName);
@@ -2307,7 +2393,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
const QString varName = m_driver->findOrInsertWidget(w);
// columns
- Item item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
+ Item item("QTreeWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
const auto &columns = w->elementColumn();
for (int i = 0; i < columns.size(); ++i) {
@@ -2316,7 +2402,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
const DomPropertyMap properties = propertyMap(column->elementProperty());
addCommonInitializers(&item, properties, i);
- if (const DomProperty *p = properties.value(QLatin1String("text"))) {
+ if (const DomProperty *p = properties.value("text"_L1)) {
DomString *str = p->elementString();
if (str && str->text().isEmpty()) {
m_output << m_indent << varName << language::derefPointer
@@ -2326,7 +2412,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
}
}
const QString itemName = item.writeSetupUi(QString(), Item::DontConstruct);
- item.writeRetranslateUi(varName + language::derefPointer + QLatin1String("headerItem()"));
+ item.writeRetranslateUi(varName + language::derefPointer + "headerItem()"_L1);
if (!itemName.isNull()) {
m_output << m_indent << varName << language::derefPointer
<< "setHeaderItem(" << itemName << ')' << language::eol;
@@ -2338,7 +2424,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
QString tempName = disableSorting(w, varName);
const auto items = initializeTreeWidgetItems(w->elementItem());
- for (int i = 0; i < items.count(); i++) {
+ for (int i = 0; i < items.size(); i++) {
Item *itm = items[i];
itm->writeSetupUi(varName);
QString parentPath;
@@ -2369,7 +2455,7 @@ WriteInitialization::Items WriteInitialization::initializeTreeWidgetItems(const
for (int i = 0; i < numDomItems; ++i) {
const DomItem *domItem = domItems.at(i);
- Item *item = new Item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
+ Item *item = new Item("QTreeWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
items << item;
QHash<QString, DomProperty *> map;
@@ -2377,7 +2463,7 @@ WriteInitialization::Items WriteInitialization::initializeTreeWidgetItems(const
int col = -1;
const DomPropertyList properties = domItem->elementProperty();
for (DomProperty *p : properties) {
- if (p->attributeName() == QLatin1String("text")) {
+ if (p->attributeName() == "text"_L1) {
if (!map.isEmpty()) {
addCommonInitializers(item, map, col);
map.clear();
@@ -2388,7 +2474,7 @@ WriteInitialization::Items WriteInitialization::initializeTreeWidgetItems(const
}
addCommonInitializers(item, map, col);
// AbstractFromBuilder saves flags last, so they always end up in the last column's map.
- addQtFlagsInitializer(item, map, QLatin1String("flags"));
+ addQtFlagsInitializer(item, map, "flags"_L1);
const auto subItems = initializeTreeWidgetItems(domItem->elementItem());
for (Item *subItem : subItems)
@@ -2418,7 +2504,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
if (!column->elementProperty().isEmpty()) {
const DomPropertyMap properties = propertyMap(column->elementProperty());
- Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
+ Item item("QTableWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
addCommonInitializers(&item, properties);
QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
@@ -2448,7 +2534,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
if (!row->elementProperty().isEmpty()) {
const DomPropertyMap properties = propertyMap(row->elementProperty());
- Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
+ Item item("QTableWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
addCommonInitializers(&item, properties);
QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
@@ -2471,8 +2557,8 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const int c = cell->attributeColumn();
const DomPropertyMap properties = propertyMap(cell->elementProperty());
- Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
- addQtFlagsInitializer(&item, properties, QLatin1String("flags"));
+ Item item("QTableWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
+ addQtFlagsInitializer(&item, properties, "flags"_L1);
addCommonInitializers(&item, properties);
QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
@@ -2524,7 +2610,7 @@ QString WriteInitialization::trCall(const QString &str, const QString &commentHi
void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWidget*/)
{
const QString menuName = m_driver->findOrInsertWidget(w);
- const QString menuAction = menuName + QLatin1String("Action");
+ const QString menuAction = menuName + "Action"_L1;
const DomAction *action = m_driver->actionByName(menuAction);
if (action && action->hasAttributeMenu()) {
@@ -2619,7 +2705,7 @@ ConnectionSyntax WriteInitialization::connectionSyntax(const language::SignalSlo
return ConnectionSyntax::StringBased;
}
- return sender.signature.endsWith(QLatin1String("()"))
+ return sender.signature.endsWith("()"_L1)
|| (!isCustomWidget(sender.className) && !isCustomWidget(receiver.className))
? ConnectionSyntax::MemberFunctionPtr : ConnectionSyntax::StringBased;
}
@@ -2641,14 +2727,21 @@ void WriteInitialization::acceptConnection(DomConnection *connection)
return;
}
const QString senderSignature = connection->elementSignal();
+ const QString slotSignature = connection->elementSlot();
+ const bool senderAmbiguous = m_uic->customWidgetsInfo()->isAmbiguousSignal(senderDecl.className,
+ senderSignature);
+ const bool slotAmbiguous = m_uic->customWidgetsInfo()->isAmbiguousSlot(receiverDecl.className,
+ slotSignature);
+
language::SignalSlotOptions signalOptions;
- if (m_uic->customWidgetsInfo()->isAmbiguousSignal(senderDecl.className, senderSignature))
- signalOptions.setFlag(language::SignalSlotOption::Ambiguous);
+ signalOptions.setFlag(language::SignalSlotOption::Ambiguous, senderAmbiguous);
+ language::SignalSlotOptions slotOptions;
+ slotOptions.setFlag(language::SignalSlotOption::Ambiguous, slotAmbiguous);
language::SignalSlot theSignal{senderDecl.name, senderSignature,
senderDecl.className, signalOptions};
- language::SignalSlot theSlot{receiverDecl.name, connection->elementSlot(),
- receiverDecl.className, {}};
+ language::SignalSlot theSlot{receiverDecl.name, slotSignature,
+ receiverDecl.className, slotOptions};
m_output << m_indent;
language::formatConnection(m_output, theSignal, theSlot,
@@ -2719,7 +2812,7 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
if (generateMultiDirective)
generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives);
- const QString uniqueName = m_driver->unique(QLatin1String("__") + m_itemClassName.toLower());
+ const QString uniqueName = m_driver->unique("__"_L1 + m_itemClassName.toLower());
m_setupUiStream << m_indent;
if (language::language() == Language::Cpp)
m_setupUiStream << m_itemClassName << " *";
@@ -2743,7 +2836,7 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
m_setupUiStream << language::closeQtConfig(it.key());
++it;
}
- for (Item *child : qAsConst(m_children))
+ for (Item *child : std::as_const(m_children))
child->writeSetupUi(uniqueName);
return uniqueName;
}
@@ -2756,7 +2849,7 @@ void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath)
if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective)
generateMultiDirectiveBegin(m_retranslateUiStream, m_retranslateUiData.directives);
- const QString uniqueName = m_driver->unique(QLatin1String("___") + m_itemClassName.toLower());
+ const QString uniqueName = m_driver->unique("___"_L1 + m_itemClassName.toLower());
m_retranslateUiStream << m_indent;
if (language::language() == Language::Cpp)
m_retranslateUiStream << m_itemClassName << " *";
diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h
index 41eca9f0cb..0973def52d 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.h
+++ b/src/tools/uic/cpp/cppwriteinitialization.h
@@ -1,36 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CPPWRITEINITIALIZATION_H
#define CPPWRITEINITIALIZATION_H
#include "treewalker.h"
-#include <qpair.h>
#include <qhash.h>
#include <qset.h>
#include <qmap.h>
@@ -144,7 +118,7 @@ private:
QString iconCall(const DomProperty *prop);
QString pixCall(const DomProperty *prop) const;
- QString pixCall(const QString &type, const QString &text) const;
+ QString pixCall(QLatin1StringView type, const QString &text) const;
QString trCall(const QString &str, const QString &comment = QString(), const QString &id = QString()) const;
QString trCall(DomString *str, const QString &defaultString = QString()) const;
QString noTrCall(DomString *str, const QString &defaultString = QString()) const;
@@ -235,6 +209,8 @@ private:
private:
QString writeFontProperties(const DomFont *f);
QString writeIconProperties(const DomResourceIcon *i);
+ void writeThemeIconCheckAssignment(const QString &themeValue, const QString &iconName,
+ const DomResourceIcon *i);
void writePixmapFunctionIcon(QTextStream &output, const QString &iconName,
const QString &indent, const DomResourceIcon *i) const;
QString writeSizePolicy(const DomSizePolicy *sp);
diff --git a/src/tools/uic/customwidgetsinfo.cpp b/src/tools/uic/customwidgetsinfo.cpp
index 4facd2bd74..6ec418634c 100644
--- a/src/tools/uic/customwidgetsinfo.cpp
+++ b/src/tools/uic/customwidgetsinfo.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "customwidgetsinfo.h"
#include "driver.h"
@@ -35,6 +10,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
CustomWidgetsInfo::CustomWidgetsInfo() = default;
void CustomWidgetsInfo::acceptUI(DomUI *node)
@@ -101,25 +78,95 @@ bool CustomWidgetsInfo::isCustomWidgetContainer(const QString &className) const
return false;
}
+// FIXME in 7.0 - QTBUG-124241
+// Remove isAmbiguous logic when widget slots have been disambiguated.
+bool CustomWidgetsInfo::isAmbiguous(const QString &className, const QString &signature,
+ QMetaMethod::MethodType type) const
+{
+ using TypeMap = QHash<QString, QMetaMethod::MethodType>;
+ struct AmbiguousInClass {
+ QLatin1StringView className;
+ TypeMap methodMap;
+ };
+
+ static const QList<AmbiguousInClass> ambiguousList = {
+
+ {"QAction"_L1, {{"triggered"_L1, QMetaMethod::Signal}}},
+ {"QCommandLinkButton"_L1, {{"triggered"_L1, QMetaMethod::Signal},
+ {"clicked"_L1, QMetaMethod::Signal}}},
+ {"QPushButton"_L1, {{"triggered"_L1, QMetaMethod::Signal},
+ {"clicked"_L1, QMetaMethod::Signal}}},
+ {"QCheckBox"_L1, {{"triggered"_L1, QMetaMethod::Signal},
+ {"clicked"_L1, QMetaMethod::Signal}}},
+ {"QRadioButton"_L1, {{"triggered"_L1, QMetaMethod::Signal},
+ {"clicked"_L1, QMetaMethod::Signal}}},
+ {"QToolButton"_L1, {{"triggered"_L1, QMetaMethod::Signal},
+ {"clicked"_L1, QMetaMethod::Signal}}},
+ {"QLabel"_L1, {{"setNum"_L1, QMetaMethod::Slot}}},
+ {"QGraphicsView"_L1, {{"invalidateScene"_L1, QMetaMethod::Slot}}},
+ {"QListView"_L1, {{"dataChanged"_L1, QMetaMethod::Slot}}},
+ {"QColumnView"_L1, {{"dataChanged"_L1, QMetaMethod::Slot}}},
+ {"QListWidget"_L1, {{"dataChanged"_L1, QMetaMethod::Slot},
+ {"scrollToItem"_L1, QMetaMethod::Slot}}},
+ {"QTableView"_L1, {{"dataChanged"_L1, QMetaMethod::Slot}}},
+ {"QTableWidget"_L1, {{"dataChanged"_L1, QMetaMethod::Slot},
+ {"scrollToItem"_L1, QMetaMethod::Slot}}},
+ {"QTreeView"_L1, {{"dataChanged"_L1, QMetaMethod::Slot},
+ {"verticalScrollbarValueChanged"_L1, QMetaMethod::Slot},
+ {"expandRecursively"_L1, QMetaMethod::Slot}}},
+ {"QTreeWidget"_L1, {{"dataChanged"_L1, QMetaMethod::Slot},
+ {"verticalScrollbarValueChanged"_L1, QMetaMethod::Slot}
+ ,{"expandRecursively"_L1, QMetaMethod::Slot}
+ ,{"scrollToItem"_L1, QMetaMethod::Slot}}},
+ {"QUndoView"_L1, {{"dataChanged"_L1, QMetaMethod::Slot}}},
+ {"QLCDNumber"_L1, {{"display"_L1, QMetaMethod::Slot}}},
+ {"QMenuBar"_L1, {{"setVisible"_L1, QMetaMethod::Slot}}},
+ {"QTextBrowser"_L1, {{"setSource"_L1, QMetaMethod::Slot}}},
+
+ /*
+ The following widgets with ambiguities are not used in the widget designer:
+
+ {"QSplashScreen"_L1, {{"showMessage"_L1, QMetaMethod::Slot}}},
+ {"QCompleter"_L1, {{"activated"_L1, QMetaMethod::Signal},
+ {"highlighted"_L1, QMetaMethod::Signal}}},
+ {"QSystemTrayIcon"_L1, {{"showMessage"_L1, QMetaMethod::Slot}}},
+ {"QStyledItemDelegate"_L1, {{"closeEditor"_L1, QMetaMethod::Signal}}},
+ {"QErrorMessage"_L1, {{"showMessage"_L1, QMetaMethod::Slot}}},
+ {"QGraphicsDropShadowEffect"_L1, {{"setOffset"_L1, QMetaMethod::Slot}}},
+ {"QGraphicsScene"_L1, {{"invalidate"_L1, QMetaMethod::Slot}}},
+ {"QItemDelegate"_L1, {{"closeEditor"_L1, QMetaMethod::Signal}}}
+ */
+ };
+
+ for (auto it = ambiguousList.constBegin(); it != ambiguousList.constEnd(); ++it) {
+ if (extends(className, it->className)) {
+ const qsizetype pos = signature.indexOf(u'(');
+ const QString method = signature.left(pos);
+ const auto methodIterator = it->methodMap.find(method);
+ return methodIterator != it->methodMap.constEnd() && type == methodIterator.value();
+ }
+ }
+ return false;
+}
+
// Is it ambiguous, resulting in different signals for Python
// "QAbstractButton::clicked(checked=false)"
bool CustomWidgetsInfo::isAmbiguousSignal(const QString &className,
const QString &signalSignature) const
{
- if (signalSignature.startsWith(u"triggered") && extends(className, "QAction"))
- return true;
- if (signalSignature.startsWith(u"clicked(")
- && extendsOneOf(className, {u"QCommandLinkButton"_qs, u"QCheckBox"_qs,
- u"QPushButton"_qs, u"QRadioButton"_qs, u"QToolButton"_qs})) {
- return true;
- }
- return false;
+ return isAmbiguous(className, signalSignature, QMetaMethod::Signal);
+}
+
+bool CustomWidgetsInfo::isAmbiguousSlot(const QString &className,
+ const QString &signalSignature) const
+{
+ return isAmbiguous(className, signalSignature, QMetaMethod::Slot);
}
QString CustomWidgetsInfo::realClassName(const QString &className) const
{
- if (className == QLatin1String("Line"))
- return QLatin1String("QFrame");
+ if (className == "Line"_L1)
+ return u"QFrame"_s;
return className;
}
@@ -137,12 +184,12 @@ QString CustomWidgetsInfo::simpleContainerAddPageMethod(const QString &name) con
using AddPageMethod = std::pair<QString, QString>;
static const AddPageMethod addPageMethods[] = {
- {u"QStackedWidget"_qs, u"addWidget"_qs},
- {u"QToolBar"_qs, u"addWidget"_qs},
- {u"QDockWidget"_qs, u"setWidget"_qs},
- {u"QScrollArea"_qs, u"setWidget"_qs},
- {u"QSplitter"_qs, u"addWidget"_qs},
- {u"QMdiArea"_qs, u"addSubWindow"_qs}
+ {u"QStackedWidget"_s, u"addWidget"_s},
+ {u"QToolBar"_s, u"addWidget"_s},
+ {u"QDockWidget"_s, u"setWidget"_s},
+ {u"QScrollArea"_s, u"setWidget"_s},
+ {u"QSplitter"_s, u"addWidget"_s},
+ {u"QMdiArea"_s, u"addSubWindow"_s}
};
for (const auto &m : addPageMethods) {
if (extends(name, m.first))
diff --git a/src/tools/uic/customwidgetsinfo.h b/src/tools/uic/customwidgetsinfo.h
index 23e5bdd14a..f336292f2a 100644
--- a/src/tools/uic/customwidgetsinfo.h
+++ b/src/tools/uic/customwidgetsinfo.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CUSTOMWIDGETSINFO_H
#define CUSTOMWIDGETSINFO_H
@@ -32,6 +7,7 @@
#include "treewalker.h"
#include <qstringlist.h>
#include <qmap.h>
+#include <QtCore/qmetaobject.h>
QT_BEGIN_NAMESPACE
@@ -63,10 +39,14 @@ public:
bool isAmbiguousSignal(const QString &className,
const QString &signalSignature) const;
+ bool isAmbiguousSlot(const QString &className,
+ const QString &slotSignature) const;
private:
using NameCustomWidgetMap = QMap<QString, DomCustomWidget*>;
NameCustomWidgetMap m_customWidgets;
+ bool isAmbiguous(const QString &className, const QString &signature,
+ QMetaMethod::MethodType type) const;
};
QT_END_NAMESPACE
diff --git a/src/tools/uic/databaseinfo.cpp b/src/tools/uic/databaseinfo.cpp
index 9b0d1614ab..5334f06baf 100644
--- a/src/tools/uic/databaseinfo.cpp
+++ b/src/tools/uic/databaseinfo.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "databaseinfo.h"
#include "driver.h"
@@ -33,6 +8,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
DatabaseInfo::DatabaseInfo() = default;
void DatabaseInfo::acceptUI(DomUI *node)
@@ -50,11 +27,11 @@ void DatabaseInfo::acceptWidget(DomWidget *node)
{
QHash<QString, DomProperty*> properties = propertyMap(node->elementProperty());
- DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"));
+ DomProperty *frameworkCode = properties.value("frameworkCode"_L1);
if (frameworkCode && toBool(frameworkCode->elementBool()) == false)
return;
- DomProperty *db = properties.value(QLatin1String("database"));
+ DomProperty *db = properties.value("database"_L1);
if (db && db->elementStringList()) {
QStringList info = db->elementStringList()->elementString();
if (info.isEmpty() || info.constFirst().isEmpty())
diff --git a/src/tools/uic/databaseinfo.h b/src/tools/uic/databaseinfo.h
index 4015e39dbc..0d2487a56f 100644
--- a/src/tools/uic/databaseinfo.h
+++ b/src/tools/uic/databaseinfo.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef DATABASEINFO_H
#define DATABASEINFO_H
diff --git a/src/tools/uic/driver.cpp b/src/tools/uic/driver.cpp
index 8b9b4806e6..110764ee07 100644
--- a/src/tools/uic/driver.cpp
+++ b/src/tools/uic/driver.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "driver.h"
#include "uic.h"
@@ -39,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Driver::Driver()
: m_stdout(stdout, QFile::WriteOnly | QFile::Text)
{
@@ -152,7 +129,7 @@ QString Driver::normalizedName(const QString &name)
QString result = name;
std::replace_if(result.begin(), result.end(),
[] (QChar c) { return !c.isLetterOrNumber(); },
- QLatin1Char('_'));
+ u'_');
return result;
}
@@ -172,7 +149,7 @@ QString Driver::unique(const QString &instanceName, const QString &className)
} else if (!className.isEmpty()) {
name = unique(qtify(className));
} else {
- name = unique(QLatin1String("var"));
+ name = unique("var"_L1);
}
if (alreadyUsed && !className.isEmpty()) {
@@ -190,7 +167,7 @@ QString Driver::qtify(const QString &name)
{
QString qname = name;
- if (qname.at(0) == QLatin1Char('Q') || qname.at(0) == QLatin1Char('K'))
+ if (qname.at(0) == u'Q' || qname.at(0) == u'K')
qname.remove(0, 1);
for (int i = 0, size = qname.size(); i < size && qname.at(i).isUpper(); ++i)
@@ -201,8 +178,7 @@ QString Driver::qtify(const QString &name)
static bool isAnsiCCharacter(QChar c)
{
- return (c.toUpper() >= QLatin1Char('A') && c.toUpper() <= QLatin1Char('Z'))
- || c.isDigit() || c == QLatin1Char('_');
+ return (c.toUpper() >= u'A' && c.toUpper() <= u'Z') || c.isDigit() || c == u'_';
}
QString Driver::headerFileName() const
@@ -210,7 +186,7 @@ QString Driver::headerFileName() const
QString name = m_option.outputFile;
if (name.isEmpty()) {
- name = QLatin1String("ui_"); // ### use ui_ as prefix.
+ name = "ui_"_L1; // ### use ui_ as prefix.
name.append(m_option.inputFile);
}
@@ -220,23 +196,23 @@ QString Driver::headerFileName() const
QString Driver::headerFileName(const QString &fileName)
{
if (fileName.isEmpty())
- return headerFileName(QLatin1String("noname"));
+ return headerFileName(u"noname"_s);
QFileInfo info(fileName);
QString baseName = info.baseName();
// Transform into a valid C++ identifier
if (!baseName.isEmpty() && baseName.at(0).isDigit())
- baseName.prepend(QLatin1Char('_'));
+ baseName.prepend(u'_');
for (int i = 0; i < baseName.size(); ++i) {
QChar c = baseName.at(i);
if (!isAnsiCCharacter(c)) {
// Replace character by its unicode value
QString hex = QString::number(c.unicode(), 16);
- baseName.replace(i, 1, QLatin1Char('_') + hex + QLatin1Char('_'));
+ baseName.replace(i, 1, u'_' + hex + u'_');
i += hex.size() + 1;
}
}
- return baseName.toUpper() + QLatin1String("_H");
+ return baseName.toUpper() + "_H"_L1;
}
bool Driver::printDependencies(const QString &fileName)
@@ -269,9 +245,10 @@ bool Driver::uic(const QString &fileName, DomUI *ui, QTextStream *out)
bool Driver::uic(const QString &fileName, QTextStream *out)
{
QFile f;
- if (fileName.isEmpty())
- f.open(stdin, QIODevice::ReadOnly);
- else {
+ if (fileName.isEmpty()) {
+ if (!f.open(stdin, QIODevice::ReadOnly))
+ return false;
+ } else {
f.setFileName(fileName);
if (!f.open(QIODevice::ReadOnly))
return false;
diff --git a/src/tools/uic/driver.h b/src/tools/uic/driver.h
index 45ec23b4aa..8c54d03d83 100644
--- a/src/tools/uic/driver.h
+++ b/src/tools/uic/driver.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef DRIVER_H
#define DRIVER_H
diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
index 4a5f0ea309..d46b788419 100644
--- a/src/tools/uic/main.cpp
+++ b/src/tools/uic/main.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "uic.h"
#include "option.h"
@@ -38,15 +13,49 @@
#include <qcoreapplication.h>
#include <qcommandlineoption.h>
#include <qcommandlineparser.h>
+#include <qfileinfo.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+static const char pythonPathVar[] = "PYTHONPATH";
+
+// From the Python paths, find the component the UI file is under
+static QString pythonRoot(const QString &pythonPath, const QString &uiFileIn)
+{
+#ifdef Q_OS_WIN
+ static const Qt::CaseSensitivity fsSensitivity = Qt::CaseInsensitive;
+#else
+ static const Qt::CaseSensitivity fsSensitivity = Qt::CaseSensitive;
+#endif
+
+ if (pythonPath.isEmpty() || uiFileIn.isEmpty())
+ return {};
+ const QString uiFile = QFileInfo(uiFileIn).canonicalFilePath();
+ if (uiFile.isEmpty())
+ return {};
+ const auto uiFileSize = uiFile.size();
+ const auto paths = pythonPath.split(QDir::listSeparator(), Qt::SkipEmptyParts);
+ for (const auto &path : paths) {
+ const QString canonicalPath = QFileInfo(path).canonicalFilePath();
+ const auto canonicalPathSize = canonicalPath.size();
+ if (uiFileSize > canonicalPathSize
+ && uiFile.at(canonicalPathSize) == u'/'
+ && uiFile.startsWith(canonicalPath, fsSensitivity)) {
+ return canonicalPath;
+ }
+ }
+ return {};
+}
+
int runUic(int argc, char *argv[])
{
- qSetGlobalQHashSeed(0); // set the hash seed to 0
+ QHashSeed::setDeterministicGlobalSeed();
QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationVersion(QString::fromLatin1(QT_VERSION_STR));
+ const QString version = QString::fromLatin1(qVersion());
+ QCoreApplication::setApplicationVersion(version);
Driver driver;
@@ -54,70 +63,89 @@ int runUic(int argc, char *argv[])
// If you use this code as an example for a translated app, make sure to translate the strings.
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- parser.setApplicationDescription(QStringLiteral("Qt User Interface Compiler version %1").arg(QString::fromLatin1(QT_VERSION_STR)));
+ parser.setApplicationDescription(u"Qt User Interface Compiler version %1"_s.arg(version));
parser.addHelpOption();
parser.addVersionOption();
- QCommandLineOption dependenciesOption(QStringList() << QStringLiteral("d") << QStringLiteral("dependencies"));
- dependenciesOption.setDescription(QStringLiteral("Display the dependencies."));
+ QCommandLineOption dependenciesOption(QStringList{u"d"_s, u"dependencies"_s});
+ dependenciesOption.setDescription(u"Display the dependencies."_s);
parser.addOption(dependenciesOption);
- QCommandLineOption outputOption(QStringList() << QStringLiteral("o") << QStringLiteral("output"));
- outputOption.setDescription(QStringLiteral("Place the output into <file>"));
- outputOption.setValueName(QStringLiteral("file"));
+ QCommandLineOption outputOption(QStringList{u"o"_s, u"output"_s});
+ outputOption.setDescription(u"Place the output into <file>"_s);
+ outputOption.setValueName(u"file"_s);
parser.addOption(outputOption);
- QCommandLineOption noAutoConnectionOption(QStringList() << QStringLiteral("a") << QStringLiteral("no-autoconnection"));
- noAutoConnectionOption.setDescription(QStringLiteral("Do not generate a call to QObject::connectSlotsByName()."));
+ QCommandLineOption noAutoConnectionOption(QStringList{u"a"_s, u"no-autoconnection"_s});
+ noAutoConnectionOption.setDescription(u"Do not generate a call to QObject::connectSlotsByName()."_s);
parser.addOption(noAutoConnectionOption);
- QCommandLineOption noProtOption(QStringList() << QStringLiteral("p") << QStringLiteral("no-protection"));
- noProtOption.setDescription(QStringLiteral("Disable header protection."));
+ QCommandLineOption noProtOption(QStringList{u"p"_s, u"no-protection"_s});
+ noProtOption.setDescription(u"Disable header protection."_s);
parser.addOption(noProtOption);
- QCommandLineOption noImplicitIncludesOption(QStringList() << QStringLiteral("n") << QStringLiteral("no-implicit-includes"));
- noImplicitIncludesOption.setDescription(QStringLiteral("Disable generation of #include-directives."));
+ QCommandLineOption noImplicitIncludesOption(QStringList{u"n"_s, u"no-implicit-includes"_s});
+ noImplicitIncludesOption.setDescription(u"Disable generation of #include-directives."_s);
parser.addOption(noImplicitIncludesOption);
- QCommandLineOption postfixOption(QStringLiteral("postfix"));
- postfixOption.setDescription(QStringLiteral("Postfix to add to all generated classnames."));
- postfixOption.setValueName(QStringLiteral("postfix"));
+ QCommandLineOption postfixOption(u"postfix"_s);
+ postfixOption.setDescription(u"Postfix to add to all generated classnames."_s);
+ postfixOption.setValueName(u"postfix"_s);
parser.addOption(postfixOption);
- QCommandLineOption translateOption(QStringList() << QStringLiteral("tr") << QStringLiteral("translate"));
- translateOption.setDescription(QStringLiteral("Use <function> for i18n."));
- translateOption.setValueName(QStringLiteral("function"));
+ QCommandLineOption noQtNamespaceOption(u"no-qt-namespace"_s);
+ noQtNamespaceOption.setDescription(
+ u"Disable wrapping the definition of the generated class in QT_{BEGIN,END}_NAMESPACE."_s);
+ parser.addOption(noQtNamespaceOption);
+
+ QCommandLineOption translateOption(QStringList{u"tr"_s, u"translate"_s});
+ translateOption.setDescription(u"Use <function> for i18n."_s);
+ translateOption.setValueName(u"function"_s);
parser.addOption(translateOption);
- QCommandLineOption includeOption(QStringList() << QStringLiteral("include"));
- includeOption.setDescription(QStringLiteral("Add #include <include-file> to <file>."));
- includeOption.setValueName(QStringLiteral("include-file"));
+ QCommandLineOption includeOption(QStringList{u"include"_s});
+ includeOption.setDescription(u"Add #include <include-file> to <file>."_s);
+ includeOption.setValueName(u"include-file"_s);
parser.addOption(includeOption);
- QCommandLineOption generatorOption(QStringList() << QStringLiteral("g") << QStringLiteral("generator"));
- generatorOption.setDescription(QStringLiteral("Select generator."));
- generatorOption.setValueName(QStringLiteral("python|cpp"));
+ QCommandLineOption generatorOption(QStringList{u"g"_s, u"generator"_s});
+ generatorOption.setDescription(u"Select generator."_s);
+ generatorOption.setValueName(u"python|cpp"_s);
parser.addOption(generatorOption);
- QCommandLineOption connectionsOption(QStringList{QStringLiteral("c"), QStringLiteral("connections")});
- connectionsOption.setDescription(QStringLiteral("Connection syntax."));
- connectionsOption.setValueName(QStringLiteral("pmf|string"));
+ QCommandLineOption connectionsOption(QStringList{u"c"_s, u"connections"_s});
+ connectionsOption.setDescription(u"Connection syntax."_s);
+ connectionsOption.setValueName(u"pmf|string"_s);
parser.addOption(connectionsOption);
- QCommandLineOption idBasedOption(QStringLiteral("idbased"));
- idBasedOption.setDescription(QStringLiteral("Use id based function for i18n"));
+ QCommandLineOption idBasedOption(u"idbased"_s);
+ idBasedOption.setDescription(u"Use id based function for i18n"_s);
parser.addOption(idBasedOption);
- QCommandLineOption fromImportsOption(QStringLiteral("from-imports"));
- fromImportsOption.setDescription(QStringLiteral("Python: generate imports relative to '.'"));
+ QCommandLineOption fromImportsOption(u"from-imports"_s);
+ fromImportsOption.setDescription(u"Python: generate imports relative to '.'"_s);
parser.addOption(fromImportsOption);
+ QCommandLineOption absoluteImportsOption(u"absolute-imports"_s);
+ absoluteImportsOption.setDescription(u"Python: generate absolute imports"_s);
+ parser.addOption(absoluteImportsOption);
+
+ // FIXME Qt 7: Flip the default?
+ QCommandLineOption rcPrefixOption(u"rc-prefix"_s);
+ rcPrefixOption.setDescription(uR"(Python: Generate "rc_file" instead of "file_rc" import)"_s);
+ parser.addOption(rcPrefixOption);
+
// FIXME Qt 7: Remove?
- QCommandLineOption useStarImportsOption(QStringLiteral("star-imports"));
- useStarImportsOption.setDescription(QStringLiteral("Python: Use * imports"));
+ QCommandLineOption useStarImportsOption(u"star-imports"_s);
+ useStarImportsOption.setDescription(u"Python: Use * imports"_s);
parser.addOption(useStarImportsOption);
- parser.addPositionalArgument(QStringLiteral("[uifile]"), QStringLiteral("Input file (*.ui), otherwise stdin."));
+ QCommandLineOption pythonPathOption(u"python-paths"_s);
+ pythonPathOption.setDescription(u"Python paths for --absolute-imports."_s);
+ pythonPathOption.setValueName(u"pathlist"_s);
+ parser.addOption(pythonPathOption);
+
+ parser.addPositionalArgument(u"[uifile]"_s, u"Input file (*.ui), otherwise stdin."_s);
parser.process(app);
@@ -126,31 +154,44 @@ int runUic(int argc, char *argv[])
driver.option().autoConnection = !parser.isSet(noAutoConnectionOption);
driver.option().headerProtection = !parser.isSet(noProtOption);
driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption);
+ driver.option().qtNamespace = !parser.isSet(noQtNamespaceOption);
driver.option().idBased = parser.isSet(idBasedOption);
- driver.option().fromImports = parser.isSet(fromImportsOption);
- driver.option().useStarImports = parser.isSet(useStarImportsOption);
driver.option().postfix = parser.value(postfixOption);
driver.option().translateFunction = parser.value(translateOption);
driver.option().includeFile = parser.value(includeOption);
if (parser.isSet(connectionsOption)) {
const auto value = parser.value(connectionsOption);
- if (value == QLatin1String("pmf"))
+ if (value == "pmf"_L1)
driver.option().forceMemberFnPtrConnectionSyntax = 1;
- else if (value == QLatin1String("string"))
+ else if (value == "string"_L1)
driver.option().forceStringConnectionSyntax = 1;
}
+ const QString inputFile = parser.positionalArguments().value(0);
+
Language language = Language::Cpp;
if (parser.isSet(generatorOption)) {
- if (parser.value(generatorOption).compare(QLatin1String("python")) == 0)
+ if (parser.value(generatorOption).compare("python"_L1) == 0)
language = Language::Python;
}
language::setLanguage(language);
+ if (language == Language::Python) {
+ if (parser.isSet(fromImportsOption))
+ driver.option().pythonResourceImport = Option::PythonResourceImport::FromDot;
+ else if (parser.isSet(absoluteImportsOption))
+ driver.option().pythonResourceImport = Option::PythonResourceImport::Absolute;
+ driver.option().useStarImports = parser.isSet(useStarImportsOption);
+ if (parser.isSet(rcPrefixOption))
+ driver.option().rcPrefix = 1;
+ QString pythonPaths;
+ if (parser.isSet(pythonPathOption))
+ pythonPaths = parser.value(pythonPathOption);
+ else if (qEnvironmentVariableIsSet(pythonPathVar))
+ pythonPaths = QString::fromUtf8(qgetenv(pythonPathVar));
+ driver.option().pythonRoot = pythonRoot(pythonPaths, inputFile);
+ }
- QString inputFile;
- if (!parser.positionalArguments().isEmpty())
- inputFile = parser.positionalArguments().at(0);
- else // reading from stdin
+ if (inputFile.isEmpty()) // reading from stdin
driver.option().headerProtection = false;
if (driver.option().dependencies) {
diff --git a/src/tools/uic/option.h b/src/tools/uic/option.h
index b08aab2d3e..cfdd90fda3 100644
--- a/src/tools/uic/option.h
+++ b/src/tools/uic/option.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef OPTION_H
#define OPTION_H
@@ -36,6 +11,12 @@ QT_BEGIN_NAMESPACE
struct Option
{
+ enum class PythonResourceImport {
+ Default, // "import rc_file"
+ FromDot, // "from . import rc_file"
+ Absolute // "import path.rc_file"
+ };
+
unsigned int headerProtection : 1;
unsigned int copyrightHeader : 1;
unsigned int generateImplemetation : 1;
@@ -45,10 +26,11 @@ struct Option
unsigned int limitXPM_LineLength : 1;
unsigned int implicitIncludes: 1;
unsigned int idBased: 1;
- unsigned int fromImports: 1;
unsigned int forceMemberFnPtrConnectionSyntax: 1;
unsigned int forceStringConnectionSyntax: 1;
unsigned int useStarImports: 1;
+ unsigned int rcPrefix: 1; // Python: Generate "rc_file" instead of "file_rc" import
+ unsigned int qtNamespace: 1;
QString inputFile;
QString outputFile;
@@ -58,6 +40,9 @@ struct Option
QString postfix;
QString translateFunction;
QString includeFile;
+ QString pythonRoot;
+
+ PythonResourceImport pythonResourceImport = PythonResourceImport::Default;
Option()
: headerProtection(1),
@@ -69,17 +54,18 @@ struct Option
limitXPM_LineLength(0),
implicitIncludes(1),
idBased(0),
- fromImports(0),
forceMemberFnPtrConnectionSyntax(0),
forceStringConnectionSyntax(0),
useStarImports(0),
- prefix(QLatin1String("Ui_"))
- { indent.fill(QLatin1Char(' '), 4); }
+ rcPrefix(0),
+ qtNamespace(1),
+ prefix(QLatin1StringView("Ui_"))
+ { indent.fill(u' ', 4); }
QString messagePrefix() const
{
return inputFile.isEmpty() ?
- QString(QLatin1String("stdin")) :
+ QString(QLatin1StringView("stdin")) :
QDir::toNativeSeparators(inputFile);
}
};
diff --git a/src/tools/uic/python/pythonwritedeclaration.cpp b/src/tools/uic/python/pythonwritedeclaration.cpp
index 5122b18e23..665eb8fe76 100644
--- a/src/tools/uic/python/pythonwritedeclaration.cpp
+++ b/src/tools/uic/python/pythonwritedeclaration.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "pythonwritedeclaration.h"
#include <cppwriteinitialization.h>
@@ -38,6 +13,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace Python {
WriteDeclaration::WriteDeclaration(Uic *uic) :
@@ -51,7 +28,7 @@ WriteDeclaration::WriteDeclaration(Uic *uic) :
void WriteDeclaration::acceptUI(DomUI *node)
{
// remove any left-over C++ namespaces
- const QString qualifiedClassName = QLatin1String("Ui_") + node->elementClass()
+ const QString qualifiedClassName = "Ui_"_L1 + node->elementClass()
+ m_option.postfix;
m_output << "class " << language::fixClassName(qualifiedClassName) << "(object):\n";
diff --git a/src/tools/uic/python/pythonwritedeclaration.h b/src/tools/uic/python/pythonwritedeclaration.h
index a8d50b6fbf..6aed86f382 100644
--- a/src/tools/uic/python/pythonwritedeclaration.h
+++ b/src/tools/uic/python/pythonwritedeclaration.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PYTHONWRITEDECLARATION_H
#define PYTHONWRITEDECLARATION_H
diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp
index 0d295b483d..74eeab8387 100644
--- a/src/tools/uic/python/pythonwriteimports.cpp
+++ b/src/tools/uic/python/pythonwriteimports.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "pythonwriteimports.h"
@@ -35,12 +10,16 @@
#include <ui4.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfileinfo.h>
#include <QtCore/qtextstream.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// Generate imports for Python. Note some things differ from C++:
// - qItemView->header()->setFoo() does not require QHeaderView to be imported
// - qLabel->setFrameShape(QFrame::Box) however requires QFrame to be imported
@@ -77,20 +56,6 @@ static WriteImports::ClassesPerModule defaultClasses()
};
}
-// Change the name of a qrc file "dir/foo.qrc" file to the Python
-// module name "foo_rc" according to project conventions.
-static QString pythonResource(QString resource)
-{
- const int lastSlash = resource.lastIndexOf(QLatin1Char('/'));
- if (lastSlash != -1)
- resource.remove(0, lastSlash + 1);
- if (resource.endsWith(QLatin1String(".qrc"))) {
- resource.chop(4);
- resource.append(QLatin1String("_rc"));
- }
- return resource;
-}
-
// Helpers for WriteImports::ClassesPerModule maps
static void insertClass(const QString &module, const QString &className,
WriteImports::ClassesPerModule *c)
@@ -137,7 +102,7 @@ WriteImports::WriteImports(Uic *uic) : WriteIncludesBase(uic),
m_qtClasses(defaultClasses())
{
for (const auto &e : classInfoEntries())
- m_classToModule.insert(QLatin1String(e.klass), QLatin1String(e.module));
+ m_classToModule.insert(QLatin1StringView(e.klass), QLatin1StringView(e.module));
}
void WriteImports::acceptUI(DomUI *node)
@@ -163,17 +128,57 @@ void WriteImports::acceptUI(DomUI *node)
const auto includes = resources->elementInclude();
for (auto include : includes) {
if (include->hasAttributeLocation())
- writeImport(pythonResource(include->attributeLocation()));
+ writeResourceImport(include->attributeLocation());
}
output << '\n';
}
}
-void WriteImports::writeImport(const QString &module)
+QString WriteImports::resourceAbsolutePath(QString resource) const
+{
+ // If we know the project root, generate an absolute Python import
+ // to the resource. options. pythonRoot is the Python path component
+ // under which the UI file is.
+ const auto &options = uic()->option();
+ if (!options.inputFile.isEmpty() && !options.pythonRoot.isEmpty()) {
+ resource = QDir::cleanPath(QFileInfo(options.inputFile).canonicalPath() + u'/' + resource);
+ if (resource.size() > options.pythonRoot.size())
+ resource.remove(0, options.pythonRoot.size() + 1);
+ }
+ // If nothing is known, we assume the directory pointed by "../" is the root
+ while (resource.startsWith(u"../"))
+ resource.remove(0, 3);
+ resource.replace(u'/', u'.');
+ return resource;
+}
+
+void WriteImports::writeResourceImport(const QString &module)
{
- if (uic()->option().fromImports)
- uic()->output() << "from . ";
- uic()->output() << "import " << module << '\n';
+ const auto &options = uic()->option();
+ auto &str = uic()->output();
+
+ QString resource = QDir::cleanPath(module);
+ if (resource.endsWith(u".qrc"))
+ resource.chop(4);
+ const qsizetype basePos = resource.lastIndexOf(u'/') + 1;
+ // Change the name of a qrc file "dir/foo.qrc" file to the Python
+ // module name "foo_rc" according to project conventions.
+ if (options.rcPrefix)
+ resource.insert(basePos, u"rc_");
+ else
+ resource.append(u"_rc");
+
+ switch (options.pythonResourceImport) {
+ case Option::PythonResourceImport::Default:
+ str << "import " << QStringView{resource}.sliced(basePos) << '\n';
+ break;
+ case Option::PythonResourceImport::FromDot:
+ str << "from . import " << QStringView{resource}.sliced(basePos) << '\n';
+ break;
+ case Option::PythonResourceImport::Absolute:
+ str << "import " << resourceAbsolutePath(resource) << '\n';
+ break;
+ }
}
void WriteImports::doAdd(const QString &className, const DomCustomWidget *dcw)
@@ -210,7 +215,7 @@ bool WriteImports::addQtClass(const QString &className)
void WriteImports::addPythonCustomWidget(const QString &className, const DomCustomWidget *node)
{
- if (className.contains(QLatin1String("::")))
+ if (className.contains("::"_L1))
return; // Exclude namespaced names (just to make tests pass).
if (addQtClass(className)) // Qt custom widgets like QQuickWidget, QAxWidget, etc
@@ -223,10 +228,14 @@ void WriteImports::addPythonCustomWidget(const QString &className, const DomCust
} else { // When we do have elementHeader, we know it's a relative import.
QString modulePath = node->elementHeader()->text();
// Replace the '/' by '.'
- modulePath.replace(QLatin1Char('/'), QLatin1Char('.'));
- // '.h' is added by default on headers for <customwidget>
- if (modulePath.endsWith(QLatin1String(".h")))
+ modulePath.replace(u'/', u'.');
+ // '.h' is added by default on headers for <customwidget>.
+ if (modulePath.endsWith(".h"_L1, Qt::CaseInsensitive))
modulePath.chop(2);
+ else if (modulePath.endsWith(".hh"_L1))
+ modulePath.chop(3);
+ else if (modulePath.endsWith(".hpp"_L1))
+ modulePath.chop(4);
insertClass(modulePath, className, &m_customWidgets);
}
}
diff --git a/src/tools/uic/python/pythonwriteimports.h b/src/tools/uic/python/pythonwriteimports.h
index 05cf48c1a1..4497b8dc33 100644
--- a/src/tools/uic/python/pythonwriteimports.h
+++ b/src/tools/uic/python/pythonwriteimports.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PYTHONWRITEIMPORTS_H
#define PYTHONWRITEIMPORTS_H
@@ -56,7 +31,8 @@ private:
void addPythonCustomWidget(const QString &className, const DomCustomWidget *dcw);
bool addQtClass(const QString &className);
void addEnumBaseClass(const QString &v);
- void writeImport(const QString &module);
+ void writeResourceImport(const QString &module);
+ QString resourceAbsolutePath(QString resource) const;
QHash<QString, QString> m_classToModule;
// Module->class (modules sorted)
diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h
index 59b2205e2d..e9e4cfde12 100644
--- a/src/tools/uic/qclass_lib_map.h
+++ b/src/tools/uic/qclass_lib_map.h
@@ -219,6 +219,7 @@ QT_CLASS_LIB(QStack, QtCore, qstack.h)
QT_CLASS_LIB(QStdWString, QtCore, qstring.h)
QT_CLASS_LIB(QString, QtCore, qstring.h)
QT_CLASS_LIB(QLatin1String, QtCore, qstring.h)
+QT_CLASS_LIB(QLatin1StringView, QtCore, qstring.h)
QT_CLASS_LIB(QCharRef, QtCore, qstring.h)
QT_CLASS_LIB(QLatin1Literal, QtCore, qstring.h)
QT_CLASS_LIB(QAbstractConcatenable, QtCore, qstringbuilder.h)
@@ -836,6 +837,7 @@ QT_CLASS_LIB(QGraphicsSvgItem, QtSvgWidgets, qgraphicssvgitem.h)
QT_CLASS_LIB(QSvgWidget, QtSvgWidgets, qsvgwidget.h)
QT_CLASS_LIB(QSvgGenerator, QtSvg, qsvggenerator.h)
QT_CLASS_LIB(QSvgRenderer, QtSvg, qsvgrenderer.h)
+QT_CLASS_LIB(QPdfView, QtPdfWidgets, qpdfview.h)
QT_CLASS_LIB(QQuickWidget, QtQuickWidgets, qquickwidget.h)
QT_CLASS_LIB(QVideoWidget, QtMultimediaWidgets, qvideowidget.h)
QT_CLASS_LIB(QWebEngineView, QtWebEngineWidgets, qwebengineview.h)
diff --git a/src/tools/uic/shared/language.cpp b/src/tools/uic/shared/language.cpp
index fc1395d403..d59688e346 100644
--- a/src/tools/uic/shared/language.cpp
+++ b/src/tools/uic/shared/language.cpp
@@ -1,37 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "language.h"
#include <QtCore/qtextstream.h>
+#include <QtCore/QList>
namespace language {
+using namespace Qt::StringLiterals;
+
static Encoding encoding = Encoding::Utf8;
static Language _language = Language::Cpp;
@@ -42,29 +20,29 @@ void setLanguage(Language l)
_language = l;
switch (_language) {
case Language::Cpp:
- derefPointer = QLatin1String("->");
+ derefPointer = u"->"_s;
listStart = '{';
listEnd = '}';
- nullPtr = QLatin1String("nullptr");
- operatorNew = QLatin1String("new ");
- qtQualifier = QLatin1String("Qt::");
- qualifier = QLatin1String("::");
- self = QLatin1String(""); // for testing: change to "this->";
- eol = QLatin1String(";\n");
- emptyString = QLatin1String("QString()");
+ nullPtr = u"nullptr"_s;
+ operatorNew = u"new "_s;
+ qtQualifier = u"Qt::"_s;
+ qualifier = u"::"_s;
+ self = u""_s; // for testing: change to "this->";
+ eol = u";\n"_s;
+ emptyString = u"QString()"_s;
encoding = Encoding::Utf8;
break;
case Language::Python:
- derefPointer = QLatin1String(".");
+ derefPointer = u"."_s;
listStart = '[';
listEnd = ']';
- nullPtr = QLatin1String("None");
- operatorNew = QLatin1String("");
- qtQualifier = QLatin1String("Qt.");
- qualifier = QLatin1String(".");
- self = QLatin1String("self.");
- eol = QLatin1String("\n");
- emptyString = QLatin1String("\"\"");
+ nullPtr = u"None"_s;
+ operatorNew = u""_s;
+ qtQualifier = u"Qt."_s;
+ qualifier = u"."_s;
+ self = u"self."_s;
+ eol = u"\n"_s;
+ emptyString = u"\"\""_s;
encoding = Encoding::Unicode;
break;
}
@@ -81,9 +59,9 @@ QString self;
QString eol;
QString emptyString;
-QString cppQualifier = QLatin1String("::");
-QString cppTrue = QLatin1String("true");
-QString cppFalse = QLatin1String("false");
+QString cppQualifier = u"::"_s;
+QString cppTrue = u"true"_s;
+QString cppFalse = u"false"_s;
QTextStream &operator<<(QTextStream &str, const qtConfig &c)
{
@@ -106,97 +84,97 @@ QTextStream &operator<<(QTextStream &str, const closeQtConfig &c)
struct EnumLookup
{
int value;
- const char *valueString;
+ QLatin1StringView valueString;
};
template <int N>
-const char *lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex = 0)
+QLatin1StringView lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex = 0)
{
for (int i = 0; i < N; ++i) {
if (value == array[i].value)
return array[i].valueString;
}
- const char *defaultValue = array[defaultIndex].valueString;
+ auto defaultValue = array[defaultIndex].valueString;
qWarning("uic: Warning: Invalid enumeration value %d, defaulting to %s",
- value, defaultValue);
+ value, defaultValue.data());
return defaultValue;
}
QString fixClassName(QString className)
{
if (language() == Language::Python)
- className.replace(cppQualifier, QLatin1String("_"));
+ className.replace(cppQualifier, "_"_L1);
return className;
}
-const char *toolbarArea(int v)
+QLatin1StringView toolbarArea(int v)
{
static const EnumLookup toolBarAreas[] =
{
- {0, "NoToolBarArea"},
- {0x1, "LeftToolBarArea"},
- {0x2, "RightToolBarArea"},
- {0x4, "TopToolBarArea"},
- {0x8, "BottomToolBarArea"},
- {0xf, "AllToolBarAreas"}
+ {0, "NoToolBarArea"_L1},
+ {0x1, "LeftToolBarArea"_L1},
+ {0x2, "RightToolBarArea"_L1},
+ {0x4, "TopToolBarArea"_L1},
+ {0x8, "BottomToolBarArea"_L1},
+ {0xf, "AllToolBarAreas"_L1}
};
return lookupEnum(toolBarAreas, v);
}
-const char *sizePolicy(int v)
+QLatin1StringView sizePolicy(int v)
{
static const EnumLookup sizePolicies[] =
{
- {0, "Fixed"},
- {0x1, "Minimum"},
- {0x4, "Maximum"},
- {0x5, "Preferred"},
- {0x3, "MinimumExpanding"},
- {0x7, "Expanding"},
- {0xD, "Ignored"}
+ {0, "Fixed"_L1},
+ {0x1, "Minimum"_L1},
+ {0x4, "Maximum"_L1},
+ {0x5, "Preferred"_L1},
+ {0x3, "MinimumExpanding"_L1},
+ {0x7, "Expanding"_L1},
+ {0xD, "Ignored"_L1}
};
return lookupEnum(sizePolicies, v, 3);
}
-const char *dockWidgetArea(int v)
+QLatin1StringView dockWidgetArea(int v)
{
static const EnumLookup dockWidgetAreas[] =
{
- {0, "NoDockWidgetArea"},
- {0x1, "LeftDockWidgetArea"},
- {0x2, "RightDockWidgetArea"},
- {0x4, "TopDockWidgetArea"},
- {0x8, "BottomDockWidgetArea"},
- {0xf, "AllDockWidgetAreas"}
+ {0, "NoDockWidgetArea"_L1},
+ {0x1, "LeftDockWidgetArea"_L1},
+ {0x2, "RightDockWidgetArea"_L1},
+ {0x4, "TopDockWidgetArea"_L1},
+ {0x8, "BottomDockWidgetArea"_L1},
+ {0xf, "AllDockWidgetAreas"_L1}
};
return lookupEnum(dockWidgetAreas, v);
}
-const char *paletteColorRole(int v)
+QLatin1StringView paletteColorRole(int v)
{
static const EnumLookup colorRoles[] =
{
- {0, "WindowText"},
- {1, "Button"},
- {2, "Light"},
- {3, "Midlight"},
- {4, "Dark"},
- {5, "Mid"},
- {6, "Text"},
- {7, "BrightText"},
- {8, "ButtonText"},
- {9, "Base"},
- {10, "Window"},
- {11, "Shadow"},
- {12, "Highlight"},
- {13, "HighlightedText"},
- {14, "Link"},
- {15, "LinkVisited"},
- {16, "AlternateBase"},
- {17, "NoRole"},
- {18, "ToolTipBase"},
- {19, "ToolTipText"},
- {20, "PlaceholderText"},
+ {0, "WindowText"_L1},
+ {1, "Button"_L1},
+ {2, "Light"_L1},
+ {3, "Midlight"_L1},
+ {4, "Dark"_L1},
+ {5, "Mid"_L1},
+ {6, "Text"_L1},
+ {7, "BrightText"_L1},
+ {8, "ButtonText"_L1},
+ {9, "Base"_L1},
+ {10, "Window"_L1},
+ {11, "Shadow"_L1},
+ {12, "Highlight"_L1},
+ {13, "HighlightedText"_L1},
+ {14, "Link"_L1},
+ {15, "LinkVisited"_L1},
+ {16, "AlternateBase"_L1},
+ {17, "NoRole"_L1},
+ {18, "ToolTipBase"_L1},
+ {19, "ToolTipText"_L1},
+ {20, "PlaceholderText"_L1},
};
return lookupEnum(colorRoles, v);
}
@@ -217,7 +195,7 @@ static int formatEscapedNumber(QTextStream &str, ushort value, int base, int wid
const auto oldFieldWidth = str.fieldWidth();
const auto oldFieldAlignment = str.fieldAlignment();
const auto oldIntegerBase = str.integerBase();
- str.setPadChar(QLatin1Char('0'));
+ str.setPadChar(u'0');
str.setFieldWidth(width);
str.setFieldAlignment(QTextStream::AlignRight);
str.setIntegerBase(base);
@@ -393,29 +371,65 @@ void _formatStackVariable(QTextStream &str, const char *className, QStringView v
}
}
-enum OverloadUse {
- UseOverload,
- UseOverloadWhenNoArguments, // Use overload only when the argument list is empty,
- // in this case there is no chance of connecting
- // mismatching T against const T &
- DontUseOverload
+enum class OverloadUse {
+ Always,
+ WhenAmbiguousOrEmpty, // Use overload if
+ // - signal/slot is ambiguous
+ // - argument list is empty (chance of connecting mismatching T against const T &)
+ Never,
};
// Format a member function for a signal slot connection
-static void formatMemberFnPtr(QTextStream &str, const SignalSlot &s,
- OverloadUse useQOverload = DontUseOverload)
+static bool isConstRef(const QStringView &arg)
+{
+ return arg.startsWith(u'Q') && arg != "QPoint"_L1 && arg != "QSize"_L1;
+}
+
+static QString formatOverload(const QStringView &parameters)
+{
+ QString result = "qOverload<"_L1;
+ const auto args = QStringView{parameters}.split(u',');
+ for (qsizetype i = 0, size = args.size(); i < size; ++i) {
+ const auto &arg = args.at(i);
+ if (i > 0)
+ result += u',';
+ const bool constRef = isConstRef(arg);
+ if (constRef)
+ result += "const "_L1;
+ result += arg;
+ if (constRef)
+ result += u'&';
+ }
+ result += u'>';
+ return result;
+}
+
+static void formatMemberFnPtr(QTextStream &str, const SignalSlot &s, OverloadUse useQOverload)
{
- const int parenPos = s.signature.indexOf(QLatin1Char('('));
+ const qsizetype parenPos = s.signature.indexOf(u'(');
Q_ASSERT(parenPos >= 0);
const auto functionName = QStringView{s.signature}.left(parenPos);
const auto parameters = QStringView{s.signature}.mid(parenPos + 1,
s.signature.size() - parenPos - 2);
- const bool withOverload = useQOverload == UseOverload ||
- (useQOverload == UseOverloadWhenNoArguments && parameters.isEmpty());
+
+ const bool isAmbiguous = s.options.testFlag(SignalSlotOption::Ambiguous);
+ bool withOverload = false; // just to silence the compiler
+
+ switch (useQOverload) {
+ case OverloadUse::Always:
+ withOverload = true;
+ break;
+ case OverloadUse::Never:
+ withOverload = false;
+ break;
+ case OverloadUse::WhenAmbiguousOrEmpty:
+ withOverload = parameters.empty() || isAmbiguous;
+ break;
+ }
if (withOverload)
- str << "qOverload<" << parameters << ">(";
+ str << formatOverload(parameters) << '(';
str << '&' << s.className << "::" << functionName;
@@ -428,9 +442,9 @@ static void formatMemberFnPtrConnection(QTextStream &str,
const SignalSlot &receiver)
{
str << "QObject::connect(" << sender.name << ", ";
- formatMemberFnPtr(str, sender);
+ formatMemberFnPtr(str, sender, OverloadUse::Never);
str << ", " << receiver.name << ", ";
- formatMemberFnPtr(str, receiver, UseOverloadWhenNoArguments);
+ formatMemberFnPtr(str, receiver, OverloadUse::WhenAmbiguousOrEmpty);
str << ')';
}
@@ -469,7 +483,7 @@ void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSl
str << "[\"" << parameters << "\"]";
}
str << ".connect(" << receiver.name << '.'
- << QStringView{receiver.signature}.left(receiver.signature.indexOf(QLatin1Char('(')))
+ << QStringView{receiver.signature}.left(receiver.signature.indexOf(u'('))
<< ')';
}
break;
diff --git a/src/tools/uic/shared/language.h b/src/tools/uic/shared/language.h
index 93fd0c63be..de39122ee8 100644
--- a/src/tools/uic/shared/language.h
+++ b/src/tools/uic/shared/language.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef LANGUAGE_H
#define LANGUAGE_H
@@ -100,10 +75,10 @@ QTextStream &operator<<(QTextStream &, const closeQtConfig &c);
QString fixClassName(QString className);
-const char *toolbarArea(int v);
-const char *sizePolicy(int v);
-const char *dockWidgetArea(int v);
-const char *paletteColorRole(int v);
+QLatin1StringView toolbarArea(int v);
+QLatin1StringView sizePolicy(int v);
+QLatin1StringView dockWidgetArea(int v);
+QLatin1StringView paletteColorRole(int v);
enum class Encoding { Utf8, Unicode };
diff --git a/src/tools/uic/shared/writeincludesbase.cpp b/src/tools/uic/shared/writeincludesbase.cpp
index 6035e8694b..78f69d5391 100644
--- a/src/tools/uic/shared/writeincludesbase.cpp
+++ b/src/tools/uic/shared/writeincludesbase.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "writeincludesbase.h"
#include "ui4.h"
diff --git a/src/tools/uic/shared/writeincludesbase.h b/src/tools/uic/shared/writeincludesbase.h
index 15e57b8c36..71ddcc80d9 100644
--- a/src/tools/uic/shared/writeincludesbase.h
+++ b/src/tools/uic/shared/writeincludesbase.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 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) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef WRITEINCLUDES_BASE_H
#define WRITEINCLUDES_BASE_H
diff --git a/src/tools/uic/treewalker.cpp b/src/tools/uic/treewalker.cpp
index 4c9981580b..731017b1a2 100644
--- a/src/tools/uic/treewalker.cpp
+++ b/src/tools/uic/treewalker.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "treewalker.h"
#include "ui4.h"
diff --git a/src/tools/uic/treewalker.h b/src/tools/uic/treewalker.h
index abc5658924..ff5d032648 100644
--- a/src/tools/uic/treewalker.h
+++ b/src/tools/uic/treewalker.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef TREEWALKER_H
#define TREEWALKER_H
diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp
index a155df9b6c..d65fc4a8c3 100644
--- a/src/tools/uic/ui4.cpp
+++ b/src/tools/uic/ui4.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT!
@@ -32,6 +7,9 @@
QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
#ifdef QFORMINTERNAL_NAMESPACE
using namespace QFormInternal;
#endif
@@ -60,133 +38,133 @@ void DomUI::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("version")) {
+ if (name == u"version"_s) {
setAttributeVersion(attribute.value().toString());
continue;
}
- if (name == QLatin1String("language")) {
+ if (name == u"language"_s) {
setAttributeLanguage(attribute.value().toString());
continue;
}
- if (name == QLatin1String("displayname")) {
+ if (name == u"displayname"_s) {
setAttributeDisplayname(attribute.value().toString());
continue;
}
- if (name == QLatin1String("idbasedtr")) {
- setAttributeIdbasedtr(attribute.value() == QLatin1String("true"));
+ if (name == u"idbasedtr"_s) {
+ setAttributeIdbasedtr(attribute.value() == u"true"_s);
continue;
}
- if (name == QLatin1String("connectslotsbyname")) {
- setAttributeConnectslotsbyname(attribute.value() == QLatin1String("true"));
+ if (name == u"connectslotsbyname"_s) {
+ setAttributeConnectslotsbyname(attribute.value() == u"true"_s);
continue;
}
- if (name == QLatin1String("stdsetdef")) {
+ if (name == u"stdsetdef"_s) {
setAttributeStdsetdef(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("stdSetDef")) {
+ if (name == u"stdSetDef"_s) {
setAttributeStdSetDef(attribute.value().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("author"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"author"_s, Qt::CaseInsensitive)) {
setElementAuthor(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("comment"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"comment"_s, Qt::CaseInsensitive)) {
setElementComment(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("exportmacro"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"exportmacro"_s, Qt::CaseInsensitive)) {
setElementExportMacro(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"class"_s, Qt::CaseInsensitive)) {
setElementClass(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"widget"_s, Qt::CaseInsensitive)) {
auto *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
- if (!tag.compare(QLatin1String("layoutdefault"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"layoutdefault"_s, Qt::CaseInsensitive)) {
auto *v = new DomLayoutDefault();
v->read(reader);
setElementLayoutDefault(v);
continue;
}
- if (!tag.compare(QLatin1String("layoutfunction"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"layoutfunction"_s, Qt::CaseInsensitive)) {
auto *v = new DomLayoutFunction();
v->read(reader);
setElementLayoutFunction(v);
continue;
}
- if (!tag.compare(QLatin1String("pixmapfunction"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"pixmapfunction"_s, Qt::CaseInsensitive)) {
setElementPixmapFunction(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("customwidgets"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"customwidgets"_s, Qt::CaseInsensitive)) {
auto *v = new DomCustomWidgets();
v->read(reader);
setElementCustomWidgets(v);
continue;
}
- if (!tag.compare(QLatin1String("tabstops"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"tabstops"_s, Qt::CaseInsensitive)) {
auto *v = new DomTabStops();
v->read(reader);
setElementTabStops(v);
continue;
}
- if (!tag.compare(QLatin1String("images"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"images"_s, Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <images>.");
reader.skipCurrentElement();
continue;
}
- if (!tag.compare(QLatin1String("includes"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"includes"_s, Qt::CaseInsensitive)) {
auto *v = new DomIncludes();
v->read(reader);
setElementIncludes(v);
continue;
}
- if (!tag.compare(QLatin1String("resources"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"resources"_s, Qt::CaseInsensitive)) {
auto *v = new DomResources();
v->read(reader);
setElementResources(v);
continue;
}
- if (!tag.compare(QLatin1String("connections"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"connections"_s, Qt::CaseInsensitive)) {
auto *v = new DomConnections();
v->read(reader);
setElementConnections(v);
continue;
}
- if (!tag.compare(QLatin1String("designerdata"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"designerdata"_s, Qt::CaseInsensitive)) {
auto *v = new DomDesignerData();
v->read(reader);
setElementDesignerdata(v);
continue;
}
- if (!tag.compare(QLatin1String("slots"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"slots"_s, Qt::CaseInsensitive)) {
auto *v = new DomSlots();
v->read(reader);
setElementSlots(v);
continue;
}
- if (!tag.compare(QLatin1String("buttongroups"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"buttongroups"_s, Qt::CaseInsensitive)) {
auto *v = new DomButtonGroups();
v->read(reader);
setElementButtonGroups(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -202,73 +180,73 @@ void DomUI::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("ui") : tagName.toLower());
if (hasAttributeVersion())
- writer.writeAttribute(QStringLiteral("version"), attributeVersion());
+ writer.writeAttribute(u"version"_s, attributeVersion());
if (hasAttributeLanguage())
- writer.writeAttribute(QStringLiteral("language"), attributeLanguage());
+ writer.writeAttribute(u"language"_s, attributeLanguage());
if (hasAttributeDisplayname())
- writer.writeAttribute(QStringLiteral("displayname"), attributeDisplayname());
+ writer.writeAttribute(u"displayname"_s, attributeDisplayname());
if (hasAttributeIdbasedtr())
- writer.writeAttribute(QStringLiteral("idbasedtr"), (attributeIdbasedtr() ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeAttribute(u"idbasedtr"_s, (attributeIdbasedtr() ? u"true"_s : u"false"_s));
if (hasAttributeConnectslotsbyname())
- writer.writeAttribute(QStringLiteral("connectslotsbyname"), (attributeConnectslotsbyname() ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeAttribute(u"connectslotsbyname"_s, (attributeConnectslotsbyname() ? u"true"_s : u"false"_s));
if (hasAttributeStdsetdef())
- writer.writeAttribute(QStringLiteral("stdsetdef"), QString::number(attributeStdsetdef()));
+ writer.writeAttribute(u"stdsetdef"_s, QString::number(attributeStdsetdef()));
if (hasAttributeStdSetDef())
- writer.writeAttribute(QStringLiteral("stdsetdef"), QString::number(attributeStdSetDef()));
+ writer.writeAttribute(u"stdsetdef"_s, QString::number(attributeStdSetDef()));
if (m_children & Author)
- writer.writeTextElement(QStringLiteral("author"), m_author);
+ writer.writeTextElement(u"author"_s, m_author);
if (m_children & Comment)
- writer.writeTextElement(QStringLiteral("comment"), m_comment);
+ writer.writeTextElement(u"comment"_s, m_comment);
if (m_children & ExportMacro)
- writer.writeTextElement(QStringLiteral("exportmacro"), m_exportMacro);
+ writer.writeTextElement(u"exportmacro"_s, m_exportMacro);
if (m_children & Class)
- writer.writeTextElement(QStringLiteral("class"), m_class);
+ writer.writeTextElement(u"class"_s, m_class);
if (m_children & Widget)
- m_widget->write(writer, QStringLiteral("widget"));
+ m_widget->write(writer, u"widget"_s);
if (m_children & LayoutDefault)
- m_layoutDefault->write(writer, QStringLiteral("layoutdefault"));
+ m_layoutDefault->write(writer, u"layoutdefault"_s);
if (m_children & LayoutFunction)
- m_layoutFunction->write(writer, QStringLiteral("layoutfunction"));
+ m_layoutFunction->write(writer, u"layoutfunction"_s);
if (m_children & PixmapFunction)
- writer.writeTextElement(QStringLiteral("pixmapfunction"), m_pixmapFunction);
+ writer.writeTextElement(u"pixmapfunction"_s, m_pixmapFunction);
if (m_children & CustomWidgets)
- m_customWidgets->write(writer, QStringLiteral("customwidgets"));
+ m_customWidgets->write(writer, u"customwidgets"_s);
if (m_children & TabStops)
- m_tabStops->write(writer, QStringLiteral("tabstops"));
+ m_tabStops->write(writer, u"tabstops"_s);
if (m_children & Includes)
- m_includes->write(writer, QStringLiteral("includes"));
+ m_includes->write(writer, u"includes"_s);
if (m_children & Resources)
- m_resources->write(writer, QStringLiteral("resources"));
+ m_resources->write(writer, u"resources"_s);
if (m_children & Connections)
- m_connections->write(writer, QStringLiteral("connections"));
+ m_connections->write(writer, u"connections"_s);
if (m_children & Designerdata)
- m_designerdata->write(writer, QStringLiteral("designerdata"));
+ m_designerdata->write(writer, u"designerdata"_s);
if (m_children & Slots)
- m_slots->write(writer, QStringLiteral("slots"));
+ m_slots->write(writer, u"slots"_s);
if (m_children & ButtonGroups)
- m_buttonGroups->write(writer, QStringLiteral("buttongroups"));
+ m_buttonGroups->write(writer, u"buttongroups"_s);
writer.writeEndElement();
}
@@ -582,13 +560,13 @@ void DomIncludes::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("include"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"include"_s, Qt::CaseInsensitive)) {
auto *v = new DomInclude();
v->read(reader);
m_include.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -604,7 +582,7 @@ void DomIncludes::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("includes") : tagName.toLower());
for (DomInclude *v : m_include)
- v->write(writer, QStringLiteral("include"));
+ v->write(writer, u"include"_s);
writer.writeEndElement();
}
@@ -622,22 +600,22 @@ void DomInclude::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("location")) {
+ if (name == u"location"_s) {
setAttributeLocation(attribute.value().toString());
continue;
}
- if (name == QLatin1String("impldecl")) {
+ if (name == u"impldecl"_s) {
setAttributeImpldecl(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -657,10 +635,10 @@ void DomInclude::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("include") : tagName.toLower());
if (hasAttributeLocation())
- writer.writeAttribute(QStringLiteral("location"), attributeLocation());
+ writer.writeAttribute(u"location"_s, attributeLocation());
if (hasAttributeImpldecl())
- writer.writeAttribute(QStringLiteral("impldecl"), attributeImpldecl());
+ writer.writeAttribute(u"impldecl"_s, attributeImpldecl());
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -679,24 +657,24 @@ void DomResources::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("include"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"include"_s, Qt::CaseInsensitive)) {
auto *v = new DomResource();
v->read(reader);
m_include.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -712,10 +690,10 @@ void DomResources::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resources") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
for (DomResource *v : m_include)
- v->write(writer, QStringLiteral("include"));
+ v->write(writer, u"include"_s);
writer.writeEndElement();
}
@@ -733,18 +711,18 @@ void DomResource::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("location")) {
+ if (name == u"location"_s) {
setAttributeLocation(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -760,7 +738,7 @@ void DomResource::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resource") : tagName.toLower());
if (hasAttributeLocation())
- writer.writeAttribute(QStringLiteral("location"), attributeLocation());
+ writer.writeAttribute(u"location"_s, attributeLocation());
writer.writeEndElement();
}
@@ -782,42 +760,42 @@ void DomActionGroup::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("action"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"action"_s, Qt::CaseInsensitive)) {
auto *v = new DomAction();
v->read(reader);
m_action.append(v);
continue;
}
- if (!tag.compare(QLatin1String("actiongroup"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"actiongroup"_s, Qt::CaseInsensitive)) {
auto *v = new DomActionGroup();
v->read(reader);
m_actionGroup.append(v);
continue;
}
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"attribute"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -833,19 +811,19 @@ void DomActionGroup::write(QXmlStreamWriter &writer, const QString &tagName) con
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("actiongroup") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
for (DomAction *v : m_action)
- v->write(writer, QStringLiteral("action"));
+ v->write(writer, u"action"_s);
for (DomActionGroup *v : m_actionGroup)
- v->write(writer, QStringLiteral("actiongroup"));
+ v->write(writer, u"actiongroup"_s);
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
for (DomProperty *v : m_attribute)
- v->write(writer, QStringLiteral("attribute"));
+ v->write(writer, u"attribute"_s);
writer.writeEndElement();
}
@@ -887,34 +865,34 @@ void DomAction::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- if (name == QLatin1String("menu")) {
+ if (name == u"menu"_s) {
setAttributeMenu(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"attribute"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -930,16 +908,16 @@ void DomAction::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("action") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
if (hasAttributeMenu())
- writer.writeAttribute(QStringLiteral("menu"), attributeMenu());
+ writer.writeAttribute(u"menu"_s, attributeMenu());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
for (DomProperty *v : m_attribute)
- v->write(writer, QStringLiteral("attribute"));
+ v->write(writer, u"attribute"_s);
writer.writeEndElement();
}
@@ -963,18 +941,18 @@ void DomActionRef::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -990,7 +968,7 @@ void DomActionRef::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("actionref") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
writer.writeEndElement();
}
@@ -1008,30 +986,30 @@ void DomButtonGroup::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"attribute"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1047,13 +1025,13 @@ void DomButtonGroup::write(QXmlStreamWriter &writer, const QString &tagName) con
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("buttongroup") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
for (DomProperty *v : m_attribute)
- v->write(writer, QStringLiteral("attribute"));
+ v->write(writer, u"attribute"_s);
writer.writeEndElement();
}
@@ -1082,13 +1060,13 @@ void DomButtonGroups::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("buttongroup"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"buttongroup"_s, Qt::CaseInsensitive)) {
auto *v = new DomButtonGroup();
v->read(reader);
m_buttonGroup.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1104,7 +1082,7 @@ void DomButtonGroups::write(QXmlStreamWriter &writer, const QString &tagName) co
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("buttongroups") : tagName.toLower());
for (DomButtonGroup *v : m_buttonGroup)
- v->write(writer, QStringLiteral("buttongroup"));
+ v->write(writer, u"buttongroup"_s);
writer.writeEndElement();
}
@@ -1127,13 +1105,13 @@ void DomCustomWidgets::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("customwidget"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"customwidget"_s, Qt::CaseInsensitive)) {
auto *v = new DomCustomWidget();
v->read(reader);
m_customWidget.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1149,7 +1127,7 @@ void DomCustomWidgets::write(QXmlStreamWriter &writer, const QString &tagName) c
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("customwidgets") : tagName.toLower());
for (DomCustomWidget *v : m_customWidget)
- v->write(writer, QStringLiteral("customwidget"));
+ v->write(writer, u"customwidget"_s);
writer.writeEndElement();
}
@@ -1167,18 +1145,18 @@ void DomHeader::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("location")) {
+ if (name == u"location"_s) {
setAttributeLocation(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1198,7 +1176,7 @@ void DomHeader::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("header") : tagName.toLower());
if (hasAttributeLocation())
- writer.writeAttribute(QStringLiteral("location"), attributeLocation());
+ writer.writeAttribute(u"location"_s, attributeLocation());
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -1220,66 +1198,66 @@ void DomCustomWidget::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"class"_s, Qt::CaseInsensitive)) {
setElementClass(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("extends"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"extends"_s, Qt::CaseInsensitive)) {
setElementExtends(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("header"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"header"_s, Qt::CaseInsensitive)) {
auto *v = new DomHeader();
v->read(reader);
setElementHeader(v);
continue;
}
- if (!tag.compare(QLatin1String("sizehint"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"sizehint"_s, Qt::CaseInsensitive)) {
auto *v = new DomSize();
v->read(reader);
setElementSizeHint(v);
continue;
}
- if (!tag.compare(QLatin1String("addpagemethod"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"addpagemethod"_s, Qt::CaseInsensitive)) {
setElementAddPageMethod(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("container"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"container"_s, Qt::CaseInsensitive)) {
setElementContainer(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("sizepolicy"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"sizepolicy"_s, Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <sizepolicy>.");
reader.skipCurrentElement();
continue;
}
- if (!tag.compare(QLatin1String("pixmap"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"pixmap"_s, Qt::CaseInsensitive)) {
setElementPixmap(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("script"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"script"_s, Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <script>.");
reader.skipCurrentElement();
continue;
}
- if (!tag.compare(QLatin1String("properties"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"properties"_s, Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <properties>.");
reader.skipCurrentElement();
continue;
}
- if (!tag.compare(QLatin1String("slots"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"slots"_s, Qt::CaseInsensitive)) {
auto *v = new DomSlots();
v->read(reader);
setElementSlots(v);
continue;
}
- if (!tag.compare(QLatin1String("propertyspecifications"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"propertyspecifications"_s, Qt::CaseInsensitive)) {
auto *v = new DomPropertySpecifications();
v->read(reader);
setElementPropertyspecifications(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1295,31 +1273,31 @@ void DomCustomWidget::write(QXmlStreamWriter &writer, const QString &tagName) co
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("customwidget") : tagName.toLower());
if (m_children & Class)
- writer.writeTextElement(QStringLiteral("class"), m_class);
+ writer.writeTextElement(u"class"_s, m_class);
if (m_children & Extends)
- writer.writeTextElement(QStringLiteral("extends"), m_extends);
+ writer.writeTextElement(u"extends"_s, m_extends);
if (m_children & Header)
- m_header->write(writer, QStringLiteral("header"));
+ m_header->write(writer, u"header"_s);
if (m_children & SizeHint)
- m_sizeHint->write(writer, QStringLiteral("sizehint"));
+ m_sizeHint->write(writer, u"sizehint"_s);
if (m_children & AddPageMethod)
- writer.writeTextElement(QStringLiteral("addpagemethod"), m_addPageMethod);
+ writer.writeTextElement(u"addpagemethod"_s, m_addPageMethod);
if (m_children & Container)
- writer.writeTextElement(QStringLiteral("container"), QString::number(m_container));
+ writer.writeTextElement(u"container"_s, QString::number(m_container));
if (m_children & Pixmap)
- writer.writeTextElement(QStringLiteral("pixmap"), m_pixmap);
+ writer.writeTextElement(u"pixmap"_s, m_pixmap);
if (m_children & Slots)
- m_slots->write(writer, QStringLiteral("slots"));
+ m_slots->write(writer, u"slots"_s);
if (m_children & Propertyspecifications)
- m_propertyspecifications->write(writer, QStringLiteral("propertyspecifications"));
+ m_propertyspecifications->write(writer, u"propertyspecifications"_s);
writer.writeEndElement();
}
@@ -1474,22 +1452,22 @@ void DomLayoutDefault::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("spacing")) {
+ if (name == u"spacing"_s) {
setAttributeSpacing(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("margin")) {
+ if (name == u"margin"_s) {
setAttributeMargin(attribute.value().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1505,10 +1483,10 @@ void DomLayoutDefault::write(QXmlStreamWriter &writer, const QString &tagName) c
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layoutdefault") : tagName.toLower());
if (hasAttributeSpacing())
- writer.writeAttribute(QStringLiteral("spacing"), QString::number(attributeSpacing()));
+ writer.writeAttribute(u"spacing"_s, QString::number(attributeSpacing()));
if (hasAttributeMargin())
- writer.writeAttribute(QStringLiteral("margin"), QString::number(attributeMargin()));
+ writer.writeAttribute(u"margin"_s, QString::number(attributeMargin()));
writer.writeEndElement();
}
@@ -1520,22 +1498,22 @@ void DomLayoutFunction::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("spacing")) {
+ if (name == u"spacing"_s) {
setAttributeSpacing(attribute.value().toString());
continue;
}
- if (name == QLatin1String("margin")) {
+ if (name == u"margin"_s) {
setAttributeMargin(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1551,10 +1529,10 @@ void DomLayoutFunction::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layoutfunction") : tagName.toLower());
if (hasAttributeSpacing())
- writer.writeAttribute(QStringLiteral("spacing"), attributeSpacing());
+ writer.writeAttribute(u"spacing"_s, attributeSpacing());
if (hasAttributeMargin())
- writer.writeAttribute(QStringLiteral("margin"), attributeMargin());
+ writer.writeAttribute(u"margin"_s, attributeMargin());
writer.writeEndElement();
}
@@ -1570,11 +1548,11 @@ void DomTabStops::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("tabstop"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"tabstop"_s, Qt::CaseInsensitive)) {
m_tabStop.append(reader.readElementText());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1590,7 +1568,7 @@ void DomTabStops::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("tabstops") : tagName.toLower());
for (const QString &v : m_tabStop)
- writer.writeTextElement(QStringLiteral("tabstop"), v);
+ writer.writeTextElement(u"tabstop"_s, v);
writer.writeEndElement();
}
@@ -1616,60 +1594,60 @@ void DomLayout::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("class")) {
+ if (name == u"class"_s) {
setAttributeClass(attribute.value().toString());
continue;
}
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- if (name == QLatin1String("stretch")) {
+ if (name == u"stretch"_s) {
setAttributeStretch(attribute.value().toString());
continue;
}
- if (name == QLatin1String("rowstretch")) {
+ if (name == u"rowstretch"_s) {
setAttributeRowStretch(attribute.value().toString());
continue;
}
- if (name == QLatin1String("columnstretch")) {
+ if (name == u"columnstretch"_s) {
setAttributeColumnStretch(attribute.value().toString());
continue;
}
- if (name == QLatin1String("rowminimumheight")) {
+ if (name == u"rowminimumheight"_s) {
setAttributeRowMinimumHeight(attribute.value().toString());
continue;
}
- if (name == QLatin1String("columnminimumwidth")) {
+ if (name == u"columnminimumwidth"_s) {
setAttributeColumnMinimumWidth(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"attribute"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"item"_s, Qt::CaseInsensitive)) {
auto *v = new DomLayoutItem();
v->read(reader);
m_item.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1685,34 +1663,34 @@ void DomLayout::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layout") : tagName.toLower());
if (hasAttributeClass())
- writer.writeAttribute(QStringLiteral("class"), attributeClass());
+ writer.writeAttribute(u"class"_s, attributeClass());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
if (hasAttributeStretch())
- writer.writeAttribute(QStringLiteral("stretch"), attributeStretch());
+ writer.writeAttribute(u"stretch"_s, attributeStretch());
if (hasAttributeRowStretch())
- writer.writeAttribute(QStringLiteral("rowstretch"), attributeRowStretch());
+ writer.writeAttribute(u"rowstretch"_s, attributeRowStretch());
if (hasAttributeColumnStretch())
- writer.writeAttribute(QStringLiteral("columnstretch"), attributeColumnStretch());
+ writer.writeAttribute(u"columnstretch"_s, attributeColumnStretch());
if (hasAttributeRowMinimumHeight())
- writer.writeAttribute(QStringLiteral("rowminimumheight"), attributeRowMinimumHeight());
+ writer.writeAttribute(u"rowminimumheight"_s, attributeRowMinimumHeight());
if (hasAttributeColumnMinimumWidth())
- writer.writeAttribute(QStringLiteral("columnminimumwidth"), attributeColumnMinimumWidth());
+ writer.writeAttribute(u"columnminimumwidth"_s, attributeColumnMinimumWidth());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
for (DomProperty *v : m_attribute)
- v->write(writer, QStringLiteral("attribute"));
+ v->write(writer, u"attribute"_s);
for (DomLayoutItem *v : m_item)
- v->write(writer, QStringLiteral("item"));
+ v->write(writer, u"item"_s);
writer.writeEndElement();
}
@@ -1760,52 +1738,52 @@ void DomLayoutItem::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("row")) {
+ if (name == u"row"_s) {
setAttributeRow(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("column")) {
+ if (name == u"column"_s) {
setAttributeColumn(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("rowspan")) {
+ if (name == u"rowspan"_s) {
setAttributeRowSpan(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("colspan")) {
+ if (name == u"colspan"_s) {
setAttributeColSpan(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("alignment")) {
+ if (name == u"alignment"_s) {
setAttributeAlignment(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"widget"_s, Qt::CaseInsensitive)) {
auto *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
- if (!tag.compare(QLatin1String("layout"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"layout"_s, Qt::CaseInsensitive)) {
auto *v = new DomLayout();
v->read(reader);
setElementLayout(v);
continue;
}
- if (!tag.compare(QLatin1String("spacer"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"spacer"_s, Qt::CaseInsensitive)) {
auto *v = new DomSpacer();
v->read(reader);
setElementSpacer(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1821,34 +1799,34 @@ void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layoutitem") : tagName.toLower());
if (hasAttributeRow())
- writer.writeAttribute(QStringLiteral("row"), QString::number(attributeRow()));
+ writer.writeAttribute(u"row"_s, QString::number(attributeRow()));
if (hasAttributeColumn())
- writer.writeAttribute(QStringLiteral("column"), QString::number(attributeColumn()));
+ writer.writeAttribute(u"column"_s, QString::number(attributeColumn()));
if (hasAttributeRowSpan())
- writer.writeAttribute(QStringLiteral("rowspan"), QString::number(attributeRowSpan()));
+ writer.writeAttribute(u"rowspan"_s, QString::number(attributeRowSpan()));
if (hasAttributeColSpan())
- writer.writeAttribute(QStringLiteral("colspan"), QString::number(attributeColSpan()));
+ writer.writeAttribute(u"colspan"_s, QString::number(attributeColSpan()));
if (hasAttributeAlignment())
- writer.writeAttribute(QStringLiteral("alignment"), attributeAlignment());
+ writer.writeAttribute(u"alignment"_s, attributeAlignment());
switch (kind()) {
case Widget:
if (m_widget != nullptr)
- m_widget->write(writer, QStringLiteral("widget"));
+ m_widget->write(writer, u"widget"_s);
break;
case Layout:
if (m_layout != nullptr)
- m_layout->write(writer, QStringLiteral("layout"));
+ m_layout->write(writer, u"layout"_s);
break;
case Spacer:
if (m_spacer != nullptr)
- m_spacer->write(writer, QStringLiteral("spacer"));
+ m_spacer->write(writer, u"spacer"_s);
break;
default:
@@ -1911,13 +1889,13 @@ void DomRow::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1933,7 +1911,7 @@ void DomRow::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("row") : tagName.toLower());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
writer.writeEndElement();
}
@@ -1956,13 +1934,13 @@ void DomColumn::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -1978,7 +1956,7 @@ void DomColumn::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("column") : tagName.toLower());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
writer.writeEndElement();
}
@@ -2002,34 +1980,34 @@ void DomItem::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("row")) {
+ if (name == u"row"_s) {
setAttributeRow(attribute.value().toInt());
continue;
}
- if (name == QLatin1String("column")) {
+ if (name == u"column"_s) {
setAttributeColumn(attribute.value().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"item"_s, Qt::CaseInsensitive)) {
auto *v = new DomItem();
v->read(reader);
m_item.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2045,16 +2023,16 @@ void DomItem::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("item") : tagName.toLower());
if (hasAttributeRow())
- writer.writeAttribute(QStringLiteral("row"), QString::number(attributeRow()));
+ writer.writeAttribute(u"row"_s, QString::number(attributeRow()));
if (hasAttributeColumn())
- writer.writeAttribute(QStringLiteral("column"), QString::number(attributeColumn()));
+ writer.writeAttribute(u"column"_s, QString::number(attributeColumn()));
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
for (DomItem *v : m_item)
- v->write(writer, QStringLiteral("item"));
+ v->write(writer, u"item"_s);
writer.writeEndElement();
}
@@ -2102,104 +2080,104 @@ void DomWidget::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("class")) {
+ if (name == u"class"_s) {
setAttributeClass(attribute.value().toString());
continue;
}
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- if (name == QLatin1String("native")) {
- setAttributeNative(attribute.value() == QLatin1String("true"));
+ if (name == u"native"_s) {
+ setAttributeNative(attribute.value() == u"true"_s);
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"class"_s, Qt::CaseInsensitive)) {
m_class.append(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (!tag.compare(QLatin1String("script"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"script"_s, Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <script>.");
reader.skipCurrentElement();
continue;
}
- if (!tag.compare(QLatin1String("widgetdata"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"widgetdata"_s, Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <widgetdata>.");
reader.skipCurrentElement();
continue;
}
- if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"attribute"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- if (!tag.compare(QLatin1String("row"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"row"_s, Qt::CaseInsensitive)) {
auto *v = new DomRow();
v->read(reader);
m_row.append(v);
continue;
}
- if (!tag.compare(QLatin1String("column"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"column"_s, Qt::CaseInsensitive)) {
auto *v = new DomColumn();
v->read(reader);
m_column.append(v);
continue;
}
- if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"item"_s, Qt::CaseInsensitive)) {
auto *v = new DomItem();
v->read(reader);
m_item.append(v);
continue;
}
- if (!tag.compare(QLatin1String("layout"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"layout"_s, Qt::CaseInsensitive)) {
auto *v = new DomLayout();
v->read(reader);
m_layout.append(v);
continue;
}
- if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"widget"_s, Qt::CaseInsensitive)) {
auto *v = new DomWidget();
v->read(reader);
m_widget.append(v);
continue;
}
- if (!tag.compare(QLatin1String("action"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"action"_s, Qt::CaseInsensitive)) {
auto *v = new DomAction();
v->read(reader);
m_action.append(v);
continue;
}
- if (!tag.compare(QLatin1String("actiongroup"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"actiongroup"_s, Qt::CaseInsensitive)) {
auto *v = new DomActionGroup();
v->read(reader);
m_actionGroup.append(v);
continue;
}
- if (!tag.compare(QLatin1String("addaction"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"addaction"_s, Qt::CaseInsensitive)) {
auto *v = new DomActionRef();
v->read(reader);
m_addAction.append(v);
continue;
}
- if (!tag.compare(QLatin1String("zorder"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"zorder"_s, Qt::CaseInsensitive)) {
m_zOrder.append(reader.readElementText());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2215,49 +2193,49 @@ void DomWidget::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("widget") : tagName.toLower());
if (hasAttributeClass())
- writer.writeAttribute(QStringLiteral("class"), attributeClass());
+ writer.writeAttribute(u"class"_s, attributeClass());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
if (hasAttributeNative())
- writer.writeAttribute(QStringLiteral("native"), (attributeNative() ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeAttribute(u"native"_s, (attributeNative() ? u"true"_s : u"false"_s));
for (const QString &v : m_class)
- writer.writeTextElement(QStringLiteral("class"), v);
+ writer.writeTextElement(u"class"_s, v);
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
for (DomProperty *v : m_attribute)
- v->write(writer, QStringLiteral("attribute"));
+ v->write(writer, u"attribute"_s);
for (DomRow *v : m_row)
- v->write(writer, QStringLiteral("row"));
+ v->write(writer, u"row"_s);
for (DomColumn *v : m_column)
- v->write(writer, QStringLiteral("column"));
+ v->write(writer, u"column"_s);
for (DomItem *v : m_item)
- v->write(writer, QStringLiteral("item"));
+ v->write(writer, u"item"_s);
for (DomLayout *v : m_layout)
- v->write(writer, QStringLiteral("layout"));
+ v->write(writer, u"layout"_s);
for (DomWidget *v : m_widget)
- v->write(writer, QStringLiteral("widget"));
+ v->write(writer, u"widget"_s);
for (DomAction *v : m_action)
- v->write(writer, QStringLiteral("action"));
+ v->write(writer, u"action"_s);
for (DomActionGroup *v : m_actionGroup)
- v->write(writer, QStringLiteral("actiongroup"));
+ v->write(writer, u"actiongroup"_s);
for (DomActionRef *v : m_addAction)
- v->write(writer, QStringLiteral("addaction"));
+ v->write(writer, u"addaction"_s);
for (const QString &v : m_zOrder)
- writer.writeTextElement(QStringLiteral("zorder"), v);
+ writer.writeTextElement(u"zorder"_s, v);
writer.writeEndElement();
}
@@ -2345,24 +2323,24 @@ void DomSpacer::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2378,10 +2356,10 @@ void DomSpacer::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("spacer") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
writer.writeEndElement();
}
@@ -2399,30 +2377,30 @@ void DomColor::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("alpha")) {
+ if (name == u"alpha"_s) {
setAttributeAlpha(attribute.value().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("red"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"red"_s, Qt::CaseInsensitive)) {
setElementRed(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("green"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"green"_s, Qt::CaseInsensitive)) {
setElementGreen(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("blue"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"blue"_s, Qt::CaseInsensitive)) {
setElementBlue(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2438,16 +2416,16 @@ void DomColor::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("color") : tagName.toLower());
if (hasAttributeAlpha())
- writer.writeAttribute(QStringLiteral("alpha"), QString::number(attributeAlpha()));
+ writer.writeAttribute(u"alpha"_s, QString::number(attributeAlpha()));
if (m_children & Red)
- writer.writeTextElement(QStringLiteral("red"), QString::number(m_red));
+ writer.writeTextElement(u"red"_s, QString::number(m_red));
if (m_children & Green)
- writer.writeTextElement(QStringLiteral("green"), QString::number(m_green));
+ writer.writeTextElement(u"green"_s, QString::number(m_green));
if (m_children & Blue)
- writer.writeTextElement(QStringLiteral("blue"), QString::number(m_blue));
+ writer.writeTextElement(u"blue"_s, QString::number(m_blue));
writer.writeEndElement();
}
@@ -2495,24 +2473,24 @@ void DomGradientStop::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("position")) {
+ if (name == u"position"_s) {
setAttributePosition(attribute.value().toDouble());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"color"_s, Qt::CaseInsensitive)) {
auto *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2528,10 +2506,10 @@ void DomGradientStop::write(QXmlStreamWriter &writer, const QString &tagName) co
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("gradientstop") : tagName.toLower());
if (hasAttributePosition())
- writer.writeAttribute(QStringLiteral("position"), QString::number(attributePosition(), 'f', 15));
+ writer.writeAttribute(u"position"_s, QString::number(attributePosition(), 'f', 15));
if (m_children & Color)
- m_color->write(writer, QStringLiteral("color"));
+ m_color->write(writer, u"color"_s);
writer.writeEndElement();
}
@@ -2569,72 +2547,72 @@ void DomGradient::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("startx")) {
+ if (name == u"startx"_s) {
setAttributeStartX(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("starty")) {
+ if (name == u"starty"_s) {
setAttributeStartY(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("endx")) {
+ if (name == u"endx"_s) {
setAttributeEndX(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("endy")) {
+ if (name == u"endy"_s) {
setAttributeEndY(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("centralx")) {
+ if (name == u"centralx"_s) {
setAttributeCentralX(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("centraly")) {
+ if (name == u"centraly"_s) {
setAttributeCentralY(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("focalx")) {
+ if (name == u"focalx"_s) {
setAttributeFocalX(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("focaly")) {
+ if (name == u"focaly"_s) {
setAttributeFocalY(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("radius")) {
+ if (name == u"radius"_s) {
setAttributeRadius(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("angle")) {
+ if (name == u"angle"_s) {
setAttributeAngle(attribute.value().toDouble());
continue;
}
- if (name == QLatin1String("type")) {
+ if (name == u"type"_s) {
setAttributeType(attribute.value().toString());
continue;
}
- if (name == QLatin1String("spread")) {
+ if (name == u"spread"_s) {
setAttributeSpread(attribute.value().toString());
continue;
}
- if (name == QLatin1String("coordinatemode")) {
+ if (name == u"coordinatemode"_s) {
setAttributeCoordinateMode(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("gradientstop"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"gradientstop"_s, Qt::CaseInsensitive)) {
auto *v = new DomGradientStop();
v->read(reader);
m_gradientStop.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2650,46 +2628,46 @@ void DomGradient::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("gradient") : tagName.toLower());
if (hasAttributeStartX())
- writer.writeAttribute(QStringLiteral("startx"), QString::number(attributeStartX(), 'f', 15));
+ writer.writeAttribute(u"startx"_s, QString::number(attributeStartX(), 'f', 15));
if (hasAttributeStartY())
- writer.writeAttribute(QStringLiteral("starty"), QString::number(attributeStartY(), 'f', 15));
+ writer.writeAttribute(u"starty"_s, QString::number(attributeStartY(), 'f', 15));
if (hasAttributeEndX())
- writer.writeAttribute(QStringLiteral("endx"), QString::number(attributeEndX(), 'f', 15));
+ writer.writeAttribute(u"endx"_s, QString::number(attributeEndX(), 'f', 15));
if (hasAttributeEndY())
- writer.writeAttribute(QStringLiteral("endy"), QString::number(attributeEndY(), 'f', 15));
+ writer.writeAttribute(u"endy"_s, QString::number(attributeEndY(), 'f', 15));
if (hasAttributeCentralX())
- writer.writeAttribute(QStringLiteral("centralx"), QString::number(attributeCentralX(), 'f', 15));
+ writer.writeAttribute(u"centralx"_s, QString::number(attributeCentralX(), 'f', 15));
if (hasAttributeCentralY())
- writer.writeAttribute(QStringLiteral("centraly"), QString::number(attributeCentralY(), 'f', 15));
+ writer.writeAttribute(u"centraly"_s, QString::number(attributeCentralY(), 'f', 15));
if (hasAttributeFocalX())
- writer.writeAttribute(QStringLiteral("focalx"), QString::number(attributeFocalX(), 'f', 15));
+ writer.writeAttribute(u"focalx"_s, QString::number(attributeFocalX(), 'f', 15));
if (hasAttributeFocalY())
- writer.writeAttribute(QStringLiteral("focaly"), QString::number(attributeFocalY(), 'f', 15));
+ writer.writeAttribute(u"focaly"_s, QString::number(attributeFocalY(), 'f', 15));
if (hasAttributeRadius())
- writer.writeAttribute(QStringLiteral("radius"), QString::number(attributeRadius(), 'f', 15));
+ writer.writeAttribute(u"radius"_s, QString::number(attributeRadius(), 'f', 15));
if (hasAttributeAngle())
- writer.writeAttribute(QStringLiteral("angle"), QString::number(attributeAngle(), 'f', 15));
+ writer.writeAttribute(u"angle"_s, QString::number(attributeAngle(), 'f', 15));
if (hasAttributeType())
- writer.writeAttribute(QStringLiteral("type"), attributeType());
+ writer.writeAttribute(u"type"_s, attributeType());
if (hasAttributeSpread())
- writer.writeAttribute(QStringLiteral("spread"), attributeSpread());
+ writer.writeAttribute(u"spread"_s, attributeSpread());
if (hasAttributeCoordinateMode())
- writer.writeAttribute(QStringLiteral("coordinatemode"), attributeCoordinateMode());
+ writer.writeAttribute(u"coordinatemode"_s, attributeCoordinateMode());
for (DomGradientStop *v : m_gradientStop)
- v->write(writer, QStringLiteral("gradientstop"));
+ v->write(writer, u"gradientstop"_s);
writer.writeEndElement();
}
@@ -2725,36 +2703,36 @@ void DomBrush::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("brushstyle")) {
+ if (name == u"brushstyle"_s) {
setAttributeBrushStyle(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"color"_s, Qt::CaseInsensitive)) {
auto *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
}
- if (!tag.compare(QLatin1String("texture"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"texture"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
setElementTexture(v);
continue;
}
- if (!tag.compare(QLatin1String("gradient"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"gradient"_s, Qt::CaseInsensitive)) {
auto *v = new DomGradient();
v->read(reader);
setElementGradient(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2770,22 +2748,22 @@ void DomBrush::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("brush") : tagName.toLower());
if (hasAttributeBrushStyle())
- writer.writeAttribute(QStringLiteral("brushstyle"), attributeBrushStyle());
+ writer.writeAttribute(u"brushstyle"_s, attributeBrushStyle());
switch (kind()) {
case Color:
if (m_color != nullptr)
- m_color->write(writer, QStringLiteral("color"));
+ m_color->write(writer, u"color"_s);
break;
case Texture:
if (m_texture != nullptr)
- m_texture->write(writer, QStringLiteral("texture"));
+ m_texture->write(writer, u"texture"_s);
break;
case Gradient:
if (m_gradient != nullptr)
- m_gradient->write(writer, QStringLiteral("gradient"));
+ m_gradient->write(writer, u"gradient"_s);
break;
default:
@@ -2846,24 +2824,24 @@ void DomColorRole::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("role")) {
+ if (name == u"role"_s) {
setAttributeRole(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("brush"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"brush"_s, Qt::CaseInsensitive)) {
auto *v = new DomBrush();
v->read(reader);
setElementBrush(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2879,10 +2857,10 @@ void DomColorRole::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("colorrole") : tagName.toLower());
if (hasAttributeRole())
- writer.writeAttribute(QStringLiteral("role"), attributeRole());
+ writer.writeAttribute(u"role"_s, attributeRole());
if (m_children & Brush)
- m_brush->write(writer, QStringLiteral("brush"));
+ m_brush->write(writer, u"brush"_s);
writer.writeEndElement();
}
@@ -2923,19 +2901,19 @@ void DomColorGroup::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("colorrole"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"colorrole"_s, Qt::CaseInsensitive)) {
auto *v = new DomColorRole();
v->read(reader);
m_colorRole.append(v);
continue;
}
- if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"color"_s, Qt::CaseInsensitive)) {
auto *v = new DomColor();
v->read(reader);
m_color.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -2951,10 +2929,10 @@ void DomColorGroup::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("colorgroup") : tagName.toLower());
for (DomColorRole *v : m_colorRole)
- v->write(writer, QStringLiteral("colorrole"));
+ v->write(writer, u"colorrole"_s);
for (DomColor *v : m_color)
- v->write(writer, QStringLiteral("color"));
+ v->write(writer, u"color"_s);
writer.writeEndElement();
}
@@ -2984,25 +2962,25 @@ void DomPalette::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("active"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"active"_s, Qt::CaseInsensitive)) {
auto *v = new DomColorGroup();
v->read(reader);
setElementActive(v);
continue;
}
- if (!tag.compare(QLatin1String("inactive"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"inactive"_s, Qt::CaseInsensitive)) {
auto *v = new DomColorGroup();
v->read(reader);
setElementInactive(v);
continue;
}
- if (!tag.compare(QLatin1String("disabled"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"disabled"_s, Qt::CaseInsensitive)) {
auto *v = new DomColorGroup();
v->read(reader);
setElementDisabled(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3018,13 +2996,13 @@ void DomPalette::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("palette") : tagName.toLower());
if (m_children & Active)
- m_active->write(writer, QStringLiteral("active"));
+ m_active->write(writer, u"active"_s);
if (m_children & Inactive)
- m_inactive->write(writer, QStringLiteral("inactive"));
+ m_inactive->write(writer, u"inactive"_s);
if (m_children & Disabled)
- m_disabled->write(writer, QStringLiteral("disabled"));
+ m_disabled->write(writer, u"disabled"_s);
writer.writeEndElement();
}
@@ -3103,47 +3081,55 @@ void DomFont::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("family"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"family"_s, Qt::CaseInsensitive)) {
setElementFamily(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("pointsize"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"pointsize"_s, Qt::CaseInsensitive)) {
setElementPointSize(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("weight"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"weight"_s, Qt::CaseInsensitive)) {
setElementWeight(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("italic"), Qt::CaseInsensitive)) {
- setElementItalic(reader.readElementText() == QLatin1String("true"));
+ if (!tag.compare(u"italic"_s, Qt::CaseInsensitive)) {
+ setElementItalic(reader.readElementText() == u"true"_s);
continue;
}
- if (!tag.compare(QLatin1String("bold"), Qt::CaseInsensitive)) {
- setElementBold(reader.readElementText() == QLatin1String("true"));
+ if (!tag.compare(u"bold"_s, Qt::CaseInsensitive)) {
+ setElementBold(reader.readElementText() == u"true"_s);
continue;
}
- if (!tag.compare(QLatin1String("underline"), Qt::CaseInsensitive)) {
- setElementUnderline(reader.readElementText() == QLatin1String("true"));
+ if (!tag.compare(u"underline"_s, Qt::CaseInsensitive)) {
+ setElementUnderline(reader.readElementText() == u"true"_s);
continue;
}
- if (!tag.compare(QLatin1String("strikeout"), Qt::CaseInsensitive)) {
- setElementStrikeOut(reader.readElementText() == QLatin1String("true"));
+ if (!tag.compare(u"strikeout"_s, Qt::CaseInsensitive)) {
+ setElementStrikeOut(reader.readElementText() == u"true"_s);
continue;
}
- if (!tag.compare(QLatin1String("antialiasing"), Qt::CaseInsensitive)) {
- setElementAntialiasing(reader.readElementText() == QLatin1String("true"));
+ if (!tag.compare(u"antialiasing"_s, Qt::CaseInsensitive)) {
+ setElementAntialiasing(reader.readElementText() == u"true"_s);
continue;
}
- if (!tag.compare(QLatin1String("stylestrategy"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"stylestrategy"_s, Qt::CaseInsensitive)) {
setElementStyleStrategy(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("kerning"), Qt::CaseInsensitive)) {
- setElementKerning(reader.readElementText() == QLatin1String("true"));
+ if (!tag.compare(u"kerning"_s, Qt::CaseInsensitive)) {
+ setElementKerning(reader.readElementText() == u"true"_s);
+ continue;
+ }
+ if (!tag.compare(u"hintingpreference"_s, Qt::CaseInsensitive)) {
+ setElementHintingPreference(reader.readElementText());
+ continue;
+ }
+ if (!tag.compare(u"fontweight"_s, Qt::CaseInsensitive)) {
+ setElementFontWeight(reader.readElementText());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3159,34 +3145,40 @@ void DomFont::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("font") : tagName.toLower());
if (m_children & Family)
- writer.writeTextElement(QStringLiteral("family"), m_family);
+ writer.writeTextElement(u"family"_s, m_family);
if (m_children & PointSize)
- writer.writeTextElement(QStringLiteral("pointsize"), QString::number(m_pointSize));
+ writer.writeTextElement(u"pointsize"_s, QString::number(m_pointSize));
if (m_children & Weight)
- writer.writeTextElement(QStringLiteral("weight"), QString::number(m_weight));
+ writer.writeTextElement(u"weight"_s, QString::number(m_weight));
if (m_children & Italic)
- writer.writeTextElement(QStringLiteral("italic"), (m_italic ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeTextElement(u"italic"_s, (m_italic ? u"true"_s : u"false"_s));
if (m_children & Bold)
- writer.writeTextElement(QStringLiteral("bold"), (m_bold ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeTextElement(u"bold"_s, (m_bold ? u"true"_s : u"false"_s));
if (m_children & Underline)
- writer.writeTextElement(QStringLiteral("underline"), (m_underline ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeTextElement(u"underline"_s, (m_underline ? u"true"_s : u"false"_s));
if (m_children & StrikeOut)
- writer.writeTextElement(QStringLiteral("strikeout"), (m_strikeOut ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeTextElement(u"strikeout"_s, (m_strikeOut ? u"true"_s : u"false"_s));
if (m_children & Antialiasing)
- writer.writeTextElement(QStringLiteral("antialiasing"), (m_antialiasing ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeTextElement(u"antialiasing"_s, (m_antialiasing ? u"true"_s : u"false"_s));
if (m_children & StyleStrategy)
- writer.writeTextElement(QStringLiteral("stylestrategy"), m_styleStrategy);
+ writer.writeTextElement(u"stylestrategy"_s, m_styleStrategy);
if (m_children & Kerning)
- writer.writeTextElement(QStringLiteral("kerning"), (m_kerning ? QLatin1String("true") : QLatin1String("false")));
+ writer.writeTextElement(u"kerning"_s, (m_kerning ? u"true"_s : u"false"_s));
+
+ if (m_children & HintingPreference)
+ writer.writeTextElement(u"hintingpreference"_s, m_hintingPreference);
+
+ if (m_children & FontWeight)
+ writer.writeTextElement(u"fontweight"_s, m_fontWeight);
writer.writeEndElement();
}
@@ -3251,6 +3243,18 @@ void DomFont::setElementKerning(bool a)
m_kerning = a;
}
+void DomFont::setElementHintingPreference(const QString &a)
+{
+ m_children |= HintingPreference;
+ m_hintingPreference = a;
+}
+
+void DomFont::setElementFontWeight(const QString &a)
+{
+ m_children |= FontWeight;
+ m_fontWeight = a;
+}
+
void DomFont::clearElementFamily()
{
m_children &= ~Family;
@@ -3301,6 +3305,16 @@ void DomFont::clearElementKerning()
m_children &= ~Kerning;
}
+void DomFont::clearElementHintingPreference()
+{
+ m_children &= ~HintingPreference;
+}
+
+void DomFont::clearElementFontWeight()
+{
+ m_children &= ~FontWeight;
+}
+
DomPoint::~DomPoint() = default;
void DomPoint::read(QXmlStreamReader &reader)
@@ -3309,15 +3323,15 @@ void DomPoint::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"x"_s, Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"y"_s, Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3333,10 +3347,10 @@ void DomPoint::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("point") : tagName.toLower());
if (m_children & X)
- writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
+ writer.writeTextElement(u"x"_s, QString::number(m_x));
if (m_children & Y)
- writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
+ writer.writeTextElement(u"y"_s, QString::number(m_y));
writer.writeEndElement();
}
@@ -3371,23 +3385,23 @@ void DomRect::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"x"_s, Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"y"_s, Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"width"_s, Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"height"_s, Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3403,16 +3417,16 @@ void DomRect::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("rect") : tagName.toLower());
if (m_children & X)
- writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
+ writer.writeTextElement(u"x"_s, QString::number(m_x));
if (m_children & Y)
- writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
+ writer.writeTextElement(u"y"_s, QString::number(m_y));
if (m_children & Width)
- writer.writeTextElement(QStringLiteral("width"), QString::number(m_width));
+ writer.writeTextElement(u"width"_s, QString::number(m_width));
if (m_children & Height)
- writer.writeTextElement(QStringLiteral("height"), QString::number(m_height));
+ writer.writeTextElement(u"height"_s, QString::number(m_height));
writer.writeEndElement();
}
@@ -3468,22 +3482,22 @@ void DomLocale::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("language")) {
+ if (name == u"language"_s) {
setAttributeLanguage(attribute.value().toString());
continue;
}
- if (name == QLatin1String("country")) {
+ if (name == u"country"_s) {
setAttributeCountry(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3499,10 +3513,10 @@ void DomLocale::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("locale") : tagName.toLower());
if (hasAttributeLanguage())
- writer.writeAttribute(QStringLiteral("language"), attributeLanguage());
+ writer.writeAttribute(u"language"_s, attributeLanguage());
if (hasAttributeCountry())
- writer.writeAttribute(QStringLiteral("country"), attributeCountry());
+ writer.writeAttribute(u"country"_s, attributeCountry());
writer.writeEndElement();
}
@@ -3514,38 +3528,38 @@ void DomSizePolicy::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("hsizetype")) {
+ if (name == u"hsizetype"_s) {
setAttributeHSizeType(attribute.value().toString());
continue;
}
- if (name == QLatin1String("vsizetype")) {
+ if (name == u"vsizetype"_s) {
setAttributeVSizeType(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("hsizetype"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"hsizetype"_s, Qt::CaseInsensitive)) {
setElementHSizeType(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("vsizetype"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"vsizetype"_s, Qt::CaseInsensitive)) {
setElementVSizeType(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("horstretch"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"horstretch"_s, Qt::CaseInsensitive)) {
setElementHorStretch(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("verstretch"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"verstretch"_s, Qt::CaseInsensitive)) {
setElementVerStretch(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3561,22 +3575,22 @@ void DomSizePolicy::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("sizepolicy") : tagName.toLower());
if (hasAttributeHSizeType())
- writer.writeAttribute(QStringLiteral("hsizetype"), attributeHSizeType());
+ writer.writeAttribute(u"hsizetype"_s, attributeHSizeType());
if (hasAttributeVSizeType())
- writer.writeAttribute(QStringLiteral("vsizetype"), attributeVSizeType());
+ writer.writeAttribute(u"vsizetype"_s, attributeVSizeType());
if (m_children & HSizeType)
- writer.writeTextElement(QStringLiteral("hsizetype"), QString::number(m_hSizeType));
+ writer.writeTextElement(u"hsizetype"_s, QString::number(m_hSizeType));
if (m_children & VSizeType)
- writer.writeTextElement(QStringLiteral("vsizetype"), QString::number(m_vSizeType));
+ writer.writeTextElement(u"vsizetype"_s, QString::number(m_vSizeType));
if (m_children & HorStretch)
- writer.writeTextElement(QStringLiteral("horstretch"), QString::number(m_horStretch));
+ writer.writeTextElement(u"horstretch"_s, QString::number(m_horStretch));
if (m_children & VerStretch)
- writer.writeTextElement(QStringLiteral("verstretch"), QString::number(m_verStretch));
+ writer.writeTextElement(u"verstretch"_s, QString::number(m_verStretch));
writer.writeEndElement();
}
@@ -3633,15 +3647,15 @@ void DomSize::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"width"_s, Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"height"_s, Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3657,10 +3671,10 @@ void DomSize::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("size") : tagName.toLower());
if (m_children & Width)
- writer.writeTextElement(QStringLiteral("width"), QString::number(m_width));
+ writer.writeTextElement(u"width"_s, QString::number(m_width));
if (m_children & Height)
- writer.writeTextElement(QStringLiteral("height"), QString::number(m_height));
+ writer.writeTextElement(u"height"_s, QString::number(m_height));
writer.writeEndElement();
}
@@ -3695,19 +3709,19 @@ void DomDate::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("year"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"year"_s, Qt::CaseInsensitive)) {
setElementYear(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("month"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"month"_s, Qt::CaseInsensitive)) {
setElementMonth(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("day"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"day"_s, Qt::CaseInsensitive)) {
setElementDay(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3723,13 +3737,13 @@ void DomDate::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("date") : tagName.toLower());
if (m_children & Year)
- writer.writeTextElement(QStringLiteral("year"), QString::number(m_year));
+ writer.writeTextElement(u"year"_s, QString::number(m_year));
if (m_children & Month)
- writer.writeTextElement(QStringLiteral("month"), QString::number(m_month));
+ writer.writeTextElement(u"month"_s, QString::number(m_month));
if (m_children & Day)
- writer.writeTextElement(QStringLiteral("day"), QString::number(m_day));
+ writer.writeTextElement(u"day"_s, QString::number(m_day));
writer.writeEndElement();
}
@@ -3775,19 +3789,19 @@ void DomTime::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("hour"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"hour"_s, Qt::CaseInsensitive)) {
setElementHour(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("minute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"minute"_s, Qt::CaseInsensitive)) {
setElementMinute(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("second"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"second"_s, Qt::CaseInsensitive)) {
setElementSecond(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3803,13 +3817,13 @@ void DomTime::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("time") : tagName.toLower());
if (m_children & Hour)
- writer.writeTextElement(QStringLiteral("hour"), QString::number(m_hour));
+ writer.writeTextElement(u"hour"_s, QString::number(m_hour));
if (m_children & Minute)
- writer.writeTextElement(QStringLiteral("minute"), QString::number(m_minute));
+ writer.writeTextElement(u"minute"_s, QString::number(m_minute));
if (m_children & Second)
- writer.writeTextElement(QStringLiteral("second"), QString::number(m_second));
+ writer.writeTextElement(u"second"_s, QString::number(m_second));
writer.writeEndElement();
}
@@ -3855,31 +3869,31 @@ void DomDateTime::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("hour"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"hour"_s, Qt::CaseInsensitive)) {
setElementHour(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("minute"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"minute"_s, Qt::CaseInsensitive)) {
setElementMinute(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("second"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"second"_s, Qt::CaseInsensitive)) {
setElementSecond(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("year"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"year"_s, Qt::CaseInsensitive)) {
setElementYear(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("month"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"month"_s, Qt::CaseInsensitive)) {
setElementMonth(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("day"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"day"_s, Qt::CaseInsensitive)) {
setElementDay(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -3895,22 +3909,22 @@ void DomDateTime::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("datetime") : tagName.toLower());
if (m_children & Hour)
- writer.writeTextElement(QStringLiteral("hour"), QString::number(m_hour));
+ writer.writeTextElement(u"hour"_s, QString::number(m_hour));
if (m_children & Minute)
- writer.writeTextElement(QStringLiteral("minute"), QString::number(m_minute));
+ writer.writeTextElement(u"minute"_s, QString::number(m_minute));
if (m_children & Second)
- writer.writeTextElement(QStringLiteral("second"), QString::number(m_second));
+ writer.writeTextElement(u"second"_s, QString::number(m_second));
if (m_children & Year)
- writer.writeTextElement(QStringLiteral("year"), QString::number(m_year));
+ writer.writeTextElement(u"year"_s, QString::number(m_year));
if (m_children & Month)
- writer.writeTextElement(QStringLiteral("month"), QString::number(m_month));
+ writer.writeTextElement(u"month"_s, QString::number(m_month));
if (m_children & Day)
- writer.writeTextElement(QStringLiteral("day"), QString::number(m_day));
+ writer.writeTextElement(u"day"_s, QString::number(m_day));
writer.writeEndElement();
}
@@ -3991,34 +4005,34 @@ void DomStringList::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("notr")) {
+ if (name == u"notr"_s) {
setAttributeNotr(attribute.value().toString());
continue;
}
- if (name == QLatin1String("comment")) {
+ if (name == u"comment"_s) {
setAttributeComment(attribute.value().toString());
continue;
}
- if (name == QLatin1String("extracomment")) {
+ if (name == u"extracomment"_s) {
setAttributeExtraComment(attribute.value().toString());
continue;
}
- if (name == QLatin1String("id")) {
+ if (name == u"id"_s) {
setAttributeId(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"string"_s, Qt::CaseInsensitive)) {
m_string.append(reader.readElementText());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4034,19 +4048,19 @@ void DomStringList::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("stringlist") : tagName.toLower());
if (hasAttributeNotr())
- writer.writeAttribute(QStringLiteral("notr"), attributeNotr());
+ writer.writeAttribute(u"notr"_s, attributeNotr());
if (hasAttributeComment())
- writer.writeAttribute(QStringLiteral("comment"), attributeComment());
+ writer.writeAttribute(u"comment"_s, attributeComment());
if (hasAttributeExtraComment())
- writer.writeAttribute(QStringLiteral("extracomment"), attributeExtraComment());
+ writer.writeAttribute(u"extracomment"_s, attributeExtraComment());
if (hasAttributeId())
- writer.writeAttribute(QStringLiteral("id"), attributeId());
+ writer.writeAttribute(u"id"_s, attributeId());
for (const QString &v : m_string)
- writer.writeTextElement(QStringLiteral("string"), v);
+ writer.writeTextElement(u"string"_s, v);
writer.writeEndElement();
}
@@ -4064,22 +4078,22 @@ void DomResourcePixmap::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("resource")) {
+ if (name == u"resource"_s) {
setAttributeResource(attribute.value().toString());
continue;
}
- if (name == QLatin1String("alias")) {
+ if (name == u"alias"_s) {
setAttributeAlias(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4099,10 +4113,10 @@ void DomResourcePixmap::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resourcepixmap") : tagName.toLower());
if (hasAttributeResource())
- writer.writeAttribute(QStringLiteral("resource"), attributeResource());
+ writer.writeAttribute(u"resource"_s, attributeResource());
if (hasAttributeAlias())
- writer.writeAttribute(QStringLiteral("alias"), attributeAlias());
+ writer.writeAttribute(u"alias"_s, attributeAlias());
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -4127,70 +4141,70 @@ void DomResourceIcon::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("theme")) {
+ if (name == u"theme"_s) {
setAttributeTheme(attribute.value().toString());
continue;
}
- if (name == QLatin1String("resource")) {
+ if (name == u"resource"_s) {
setAttributeResource(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("normaloff"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"normaloff"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementNormalOff(v);
continue;
}
- if (!tag.compare(QLatin1String("normalon"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"normalon"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementNormalOn(v);
continue;
}
- if (!tag.compare(QLatin1String("disabledoff"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"disabledoff"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementDisabledOff(v);
continue;
}
- if (!tag.compare(QLatin1String("disabledon"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"disabledon"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementDisabledOn(v);
continue;
}
- if (!tag.compare(QLatin1String("activeoff"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"activeoff"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementActiveOff(v);
continue;
}
- if (!tag.compare(QLatin1String("activeon"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"activeon"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementActiveOn(v);
continue;
}
- if (!tag.compare(QLatin1String("selectedoff"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"selectedoff"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementSelectedOff(v);
continue;
}
- if (!tag.compare(QLatin1String("selectedon"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"selectedon"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementSelectedOn(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4210,34 +4224,34 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resourceicon") : tagName.toLower());
if (hasAttributeTheme())
- writer.writeAttribute(QStringLiteral("theme"), attributeTheme());
+ writer.writeAttribute(u"theme"_s, attributeTheme());
if (hasAttributeResource())
- writer.writeAttribute(QStringLiteral("resource"), attributeResource());
+ writer.writeAttribute(u"resource"_s, attributeResource());
if (m_children & NormalOff)
- m_normalOff->write(writer, QStringLiteral("normaloff"));
+ m_normalOff->write(writer, u"normaloff"_s);
if (m_children & NormalOn)
- m_normalOn->write(writer, QStringLiteral("normalon"));
+ m_normalOn->write(writer, u"normalon"_s);
if (m_children & DisabledOff)
- m_disabledOff->write(writer, QStringLiteral("disabledoff"));
+ m_disabledOff->write(writer, u"disabledoff"_s);
if (m_children & DisabledOn)
- m_disabledOn->write(writer, QStringLiteral("disabledon"));
+ m_disabledOn->write(writer, u"disabledon"_s);
if (m_children & ActiveOff)
- m_activeOff->write(writer, QStringLiteral("activeoff"));
+ m_activeOff->write(writer, u"activeoff"_s);
if (m_children & ActiveOn)
- m_activeOn->write(writer, QStringLiteral("activeon"));
+ m_activeOn->write(writer, u"activeon"_s);
if (m_children & SelectedOff)
- m_selectedOff->write(writer, QStringLiteral("selectedoff"));
+ m_selectedOff->write(writer, u"selectedoff"_s);
if (m_children & SelectedOn)
- m_selectedOn->write(writer, QStringLiteral("selectedon"));
+ m_selectedOn->write(writer, u"selectedon"_s);
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -4428,30 +4442,30 @@ void DomString::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("notr")) {
+ if (name == u"notr"_s) {
setAttributeNotr(attribute.value().toString());
continue;
}
- if (name == QLatin1String("comment")) {
+ if (name == u"comment"_s) {
setAttributeComment(attribute.value().toString());
continue;
}
- if (name == QLatin1String("extracomment")) {
+ if (name == u"extracomment"_s) {
setAttributeExtraComment(attribute.value().toString());
continue;
}
- if (name == QLatin1String("id")) {
+ if (name == u"id"_s) {
setAttributeId(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4471,16 +4485,16 @@ void DomString::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("string") : tagName.toLower());
if (hasAttributeNotr())
- writer.writeAttribute(QStringLiteral("notr"), attributeNotr());
+ writer.writeAttribute(u"notr"_s, attributeNotr());
if (hasAttributeComment())
- writer.writeAttribute(QStringLiteral("comment"), attributeComment());
+ writer.writeAttribute(u"comment"_s, attributeComment());
if (hasAttributeExtraComment())
- writer.writeAttribute(QStringLiteral("extracomment"), attributeExtraComment());
+ writer.writeAttribute(u"extracomment"_s, attributeExtraComment());
if (hasAttributeId())
- writer.writeAttribute(QStringLiteral("id"), attributeId());
+ writer.writeAttribute(u"id"_s, attributeId());
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -4496,15 +4510,15 @@ void DomPointF::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"x"_s, Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toDouble());
continue;
}
- if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"y"_s, Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toDouble());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4520,10 +4534,10 @@ void DomPointF::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("pointf") : tagName.toLower());
if (m_children & X)
- writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x, 'f', 15));
+ writer.writeTextElement(u"x"_s, QString::number(m_x, 'f', 15));
if (m_children & Y)
- writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y, 'f', 15));
+ writer.writeTextElement(u"y"_s, QString::number(m_y, 'f', 15));
writer.writeEndElement();
}
@@ -4558,23 +4572,23 @@ void DomRectF::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"x"_s, Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toDouble());
continue;
}
- if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"y"_s, Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toDouble());
continue;
}
- if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"width"_s, Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toDouble());
continue;
}
- if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"height"_s, Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toDouble());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4590,16 +4604,16 @@ void DomRectF::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("rectf") : tagName.toLower());
if (m_children & X)
- writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x, 'f', 15));
+ writer.writeTextElement(u"x"_s, QString::number(m_x, 'f', 15));
if (m_children & Y)
- writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y, 'f', 15));
+ writer.writeTextElement(u"y"_s, QString::number(m_y, 'f', 15));
if (m_children & Width)
- writer.writeTextElement(QStringLiteral("width"), QString::number(m_width, 'f', 15));
+ writer.writeTextElement(u"width"_s, QString::number(m_width, 'f', 15));
if (m_children & Height)
- writer.writeTextElement(QStringLiteral("height"), QString::number(m_height, 'f', 15));
+ writer.writeTextElement(u"height"_s, QString::number(m_height, 'f', 15));
writer.writeEndElement();
}
@@ -4656,15 +4670,15 @@ void DomSizeF::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"width"_s, Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toDouble());
continue;
}
- if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"height"_s, Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toDouble());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4680,10 +4694,10 @@ void DomSizeF::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("sizef") : tagName.toLower());
if (m_children & Width)
- writer.writeTextElement(QStringLiteral("width"), QString::number(m_width, 'f', 15));
+ writer.writeTextElement(u"width"_s, QString::number(m_width, 'f', 15));
if (m_children & Height)
- writer.writeTextElement(QStringLiteral("height"), QString::number(m_height, 'f', 15));
+ writer.writeTextElement(u"height"_s, QString::number(m_height, 'f', 15));
writer.writeEndElement();
}
@@ -4718,11 +4732,11 @@ void DomChar::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("unicode"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"unicode"_s, Qt::CaseInsensitive)) {
setElementUnicode(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4738,7 +4752,7 @@ void DomChar::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("char") : tagName.toLower());
if (m_children & Unicode)
- writer.writeTextElement(QStringLiteral("unicode"), QString::number(m_unicode));
+ writer.writeTextElement(u"unicode"_s, QString::number(m_unicode));
writer.writeEndElement();
}
@@ -4765,13 +4779,13 @@ void DomUrl::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"string"_s, Qt::CaseInsensitive)) {
auto *v = new DomString();
v->read(reader);
setElementString(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -4787,7 +4801,7 @@ void DomUrl::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("url") : tagName.toLower());
if (m_children & String)
- m_string->write(writer, QStringLiteral("string"));
+ m_string->write(writer, u"string"_s);
writer.writeEndElement();
}
@@ -4900,196 +4914,196 @@ void DomProperty::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- if (name == QLatin1String("stdset")) {
+ if (name == u"stdset"_s) {
setAttributeStdset(attribute.value().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("bool"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"bool"_s, Qt::CaseInsensitive)) {
setElementBool(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"color"_s, Qt::CaseInsensitive)) {
auto *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
}
- if (!tag.compare(QLatin1String("cstring"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"cstring"_s, Qt::CaseInsensitive)) {
setElementCstring(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("cursor"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"cursor"_s, Qt::CaseInsensitive)) {
setElementCursor(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("cursorshape"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"cursorshape"_s, Qt::CaseInsensitive)) {
setElementCursorShape(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("enum"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"enum"_s, Qt::CaseInsensitive)) {
setElementEnum(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("font"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"font"_s, Qt::CaseInsensitive)) {
auto *v = new DomFont();
v->read(reader);
setElementFont(v);
continue;
}
- if (!tag.compare(QLatin1String("iconset"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"iconset"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourceIcon();
v->read(reader);
setElementIconSet(v);
continue;
}
- if (!tag.compare(QLatin1String("pixmap"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"pixmap"_s, Qt::CaseInsensitive)) {
auto *v = new DomResourcePixmap();
v->read(reader);
setElementPixmap(v);
continue;
}
- if (!tag.compare(QLatin1String("palette"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"palette"_s, Qt::CaseInsensitive)) {
auto *v = new DomPalette();
v->read(reader);
setElementPalette(v);
continue;
}
- if (!tag.compare(QLatin1String("point"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"point"_s, Qt::CaseInsensitive)) {
auto *v = new DomPoint();
v->read(reader);
setElementPoint(v);
continue;
}
- if (!tag.compare(QLatin1String("rect"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"rect"_s, Qt::CaseInsensitive)) {
auto *v = new DomRect();
v->read(reader);
setElementRect(v);
continue;
}
- if (!tag.compare(QLatin1String("set"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"set"_s, Qt::CaseInsensitive)) {
setElementSet(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("locale"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"locale"_s, Qt::CaseInsensitive)) {
auto *v = new DomLocale();
v->read(reader);
setElementLocale(v);
continue;
}
- if (!tag.compare(QLatin1String("sizepolicy"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"sizepolicy"_s, Qt::CaseInsensitive)) {
auto *v = new DomSizePolicy();
v->read(reader);
setElementSizePolicy(v);
continue;
}
- if (!tag.compare(QLatin1String("size"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"size"_s, Qt::CaseInsensitive)) {
auto *v = new DomSize();
v->read(reader);
setElementSize(v);
continue;
}
- if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"string"_s, Qt::CaseInsensitive)) {
auto *v = new DomString();
v->read(reader);
setElementString(v);
continue;
}
- if (!tag.compare(QLatin1String("stringlist"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"stringlist"_s, Qt::CaseInsensitive)) {
auto *v = new DomStringList();
v->read(reader);
setElementStringList(v);
continue;
}
- if (!tag.compare(QLatin1String("number"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"number"_s, Qt::CaseInsensitive)) {
setElementNumber(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("float"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"float"_s, Qt::CaseInsensitive)) {
setElementFloat(reader.readElementText().toFloat());
continue;
}
- if (!tag.compare(QLatin1String("double"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"double"_s, Qt::CaseInsensitive)) {
setElementDouble(reader.readElementText().toDouble());
continue;
}
- if (!tag.compare(QLatin1String("date"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"date"_s, Qt::CaseInsensitive)) {
auto *v = new DomDate();
v->read(reader);
setElementDate(v);
continue;
}
- if (!tag.compare(QLatin1String("time"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"time"_s, Qt::CaseInsensitive)) {
auto *v = new DomTime();
v->read(reader);
setElementTime(v);
continue;
}
- if (!tag.compare(QLatin1String("datetime"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"datetime"_s, Qt::CaseInsensitive)) {
auto *v = new DomDateTime();
v->read(reader);
setElementDateTime(v);
continue;
}
- if (!tag.compare(QLatin1String("pointf"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"pointf"_s, Qt::CaseInsensitive)) {
auto *v = new DomPointF();
v->read(reader);
setElementPointF(v);
continue;
}
- if (!tag.compare(QLatin1String("rectf"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"rectf"_s, Qt::CaseInsensitive)) {
auto *v = new DomRectF();
v->read(reader);
setElementRectF(v);
continue;
}
- if (!tag.compare(QLatin1String("sizef"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"sizef"_s, Qt::CaseInsensitive)) {
auto *v = new DomSizeF();
v->read(reader);
setElementSizeF(v);
continue;
}
- if (!tag.compare(QLatin1String("longlong"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"longlong"_s, Qt::CaseInsensitive)) {
setElementLongLong(reader.readElementText().toLongLong());
continue;
}
- if (!tag.compare(QLatin1String("char"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"char"_s, Qt::CaseInsensitive)) {
auto *v = new DomChar();
v->read(reader);
setElementChar(v);
continue;
}
- if (!tag.compare(QLatin1String("url"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"url"_s, Qt::CaseInsensitive)) {
auto *v = new DomUrl();
v->read(reader);
setElementUrl(v);
continue;
}
- if (!tag.compare(QLatin1String("uint"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"uint"_s, Qt::CaseInsensitive)) {
setElementUInt(reader.readElementText().toUInt());
continue;
}
- if (!tag.compare(QLatin1String("ulonglong"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"ulonglong"_s, Qt::CaseInsensitive)) {
setElementULongLong(reader.readElementText().toULongLong());
continue;
}
- if (!tag.compare(QLatin1String("brush"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"brush"_s, Qt::CaseInsensitive)) {
auto *v = new DomBrush();
v->read(reader);
setElementBrush(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -5105,163 +5119,163 @@ void DomProperty::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("property") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
if (hasAttributeStdset())
- writer.writeAttribute(QStringLiteral("stdset"), QString::number(attributeStdset()));
+ writer.writeAttribute(u"stdset"_s, QString::number(attributeStdset()));
switch (kind()) {
case Bool:
- writer.writeTextElement(QStringLiteral("bool"), elementBool());
+ writer.writeTextElement(u"bool"_s, elementBool());
break;
case Color:
if (m_color != nullptr)
- m_color->write(writer, QStringLiteral("color"));
+ m_color->write(writer, u"color"_s);
break;
case Cstring:
- writer.writeTextElement(QStringLiteral("cstring"), elementCstring());
+ writer.writeTextElement(u"cstring"_s, elementCstring());
break;
case Cursor:
- writer.writeTextElement(QStringLiteral("cursor"), QString::number(elementCursor()));
+ writer.writeTextElement(u"cursor"_s, QString::number(elementCursor()));
break;
case CursorShape:
- writer.writeTextElement(QStringLiteral("cursorShape"), elementCursorShape());
+ writer.writeTextElement(u"cursorShape"_s, elementCursorShape());
break;
case Enum:
- writer.writeTextElement(QStringLiteral("enum"), elementEnum());
+ writer.writeTextElement(u"enum"_s, elementEnum());
break;
case Font:
if (m_font != nullptr)
- m_font->write(writer, QStringLiteral("font"));
+ m_font->write(writer, u"font"_s);
break;
case IconSet:
if (m_iconSet != nullptr)
- m_iconSet->write(writer, QStringLiteral("iconset"));
+ m_iconSet->write(writer, u"iconset"_s);
break;
case Pixmap:
if (m_pixmap != nullptr)
- m_pixmap->write(writer, QStringLiteral("pixmap"));
+ m_pixmap->write(writer, u"pixmap"_s);
break;
case Palette:
if (m_palette != nullptr)
- m_palette->write(writer, QStringLiteral("palette"));
+ m_palette->write(writer, u"palette"_s);
break;
case Point:
if (m_point != nullptr)
- m_point->write(writer, QStringLiteral("point"));
+ m_point->write(writer, u"point"_s);
break;
case Rect:
if (m_rect != nullptr)
- m_rect->write(writer, QStringLiteral("rect"));
+ m_rect->write(writer, u"rect"_s);
break;
case Set:
- writer.writeTextElement(QStringLiteral("set"), elementSet());
+ writer.writeTextElement(u"set"_s, elementSet());
break;
case Locale:
if (m_locale != nullptr)
- m_locale->write(writer, QStringLiteral("locale"));
+ m_locale->write(writer, u"locale"_s);
break;
case SizePolicy:
if (m_sizePolicy != nullptr)
- m_sizePolicy->write(writer, QStringLiteral("sizepolicy"));
+ m_sizePolicy->write(writer, u"sizepolicy"_s);
break;
case Size:
if (m_size != nullptr)
- m_size->write(writer, QStringLiteral("size"));
+ m_size->write(writer, u"size"_s);
break;
case String:
if (m_string != nullptr)
- m_string->write(writer, QStringLiteral("string"));
+ m_string->write(writer, u"string"_s);
break;
case StringList:
if (m_stringList != nullptr)
- m_stringList->write(writer, QStringLiteral("stringlist"));
+ m_stringList->write(writer, u"stringlist"_s);
break;
case Number:
- writer.writeTextElement(QStringLiteral("number"), QString::number(elementNumber()));
+ writer.writeTextElement(u"number"_s, QString::number(elementNumber()));
break;
case Float:
- writer.writeTextElement(QStringLiteral("float"), QString::number(elementFloat(), 'f', 8));
+ writer.writeTextElement(u"float"_s, QString::number(elementFloat(), 'f', 8));
break;
case Double:
- writer.writeTextElement(QStringLiteral("double"), QString::number(elementDouble(), 'f', 15));
+ writer.writeTextElement(u"double"_s, QString::number(elementDouble(), 'f', 15));
break;
case Date:
if (m_date != nullptr)
- m_date->write(writer, QStringLiteral("date"));
+ m_date->write(writer, u"date"_s);
break;
case Time:
if (m_time != nullptr)
- m_time->write(writer, QStringLiteral("time"));
+ m_time->write(writer, u"time"_s);
break;
case DateTime:
if (m_dateTime != nullptr)
- m_dateTime->write(writer, QStringLiteral("datetime"));
+ m_dateTime->write(writer, u"datetime"_s);
break;
case PointF:
if (m_pointF != nullptr)
- m_pointF->write(writer, QStringLiteral("pointf"));
+ m_pointF->write(writer, u"pointf"_s);
break;
case RectF:
if (m_rectF != nullptr)
- m_rectF->write(writer, QStringLiteral("rectf"));
+ m_rectF->write(writer, u"rectf"_s);
break;
case SizeF:
if (m_sizeF != nullptr)
- m_sizeF->write(writer, QStringLiteral("sizef"));
+ m_sizeF->write(writer, u"sizef"_s);
break;
case LongLong:
- writer.writeTextElement(QStringLiteral("longLong"), QString::number(elementLongLong()));
+ writer.writeTextElement(u"longLong"_s, QString::number(elementLongLong()));
break;
case Char:
if (m_char != nullptr)
- m_char->write(writer, QStringLiteral("char"));
+ m_char->write(writer, u"char"_s);
break;
case Url:
if (m_url != nullptr)
- m_url->write(writer, QStringLiteral("url"));
+ m_url->write(writer, u"url"_s);
break;
case UInt:
- writer.writeTextElement(QStringLiteral("UInt"), QString::number(elementUInt()));
+ writer.writeTextElement(u"UInt"_s, QString::number(elementUInt()));
break;
case ULongLong:
- writer.writeTextElement(QStringLiteral("uLongLong"), QString::number(elementULongLong()));
+ writer.writeTextElement(u"uLongLong"_s, QString::number(elementULongLong()));
break;
case Brush:
if (m_brush != nullptr)
- m_brush->write(writer, QStringLiteral("brush"));
+ m_brush->write(writer, u"brush"_s);
break;
default:
@@ -5660,13 +5674,13 @@ void DomConnections::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("connection"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"connection"_s, Qt::CaseInsensitive)) {
auto *v = new DomConnection();
v->read(reader);
m_connection.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -5682,7 +5696,7 @@ void DomConnections::write(QXmlStreamWriter &writer, const QString &tagName) con
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connections") : tagName.toLower());
for (DomConnection *v : m_connection)
- v->write(writer, QStringLiteral("connection"));
+ v->write(writer, u"connection"_s);
writer.writeEndElement();
}
@@ -5704,29 +5718,29 @@ void DomConnection::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("sender"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"sender"_s, Qt::CaseInsensitive)) {
setElementSender(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("signal"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"signal"_s, Qt::CaseInsensitive)) {
setElementSignal(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("receiver"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"receiver"_s, Qt::CaseInsensitive)) {
setElementReceiver(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("slot"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"slot"_s, Qt::CaseInsensitive)) {
setElementSlot(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("hints"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"hints"_s, Qt::CaseInsensitive)) {
auto *v = new DomConnectionHints();
v->read(reader);
setElementHints(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -5742,19 +5756,19 @@ void DomConnection::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connection") : tagName.toLower());
if (m_children & Sender)
- writer.writeTextElement(QStringLiteral("sender"), m_sender);
+ writer.writeTextElement(u"sender"_s, m_sender);
if (m_children & Signal)
- writer.writeTextElement(QStringLiteral("signal"), m_signal);
+ writer.writeTextElement(u"signal"_s, m_signal);
if (m_children & Receiver)
- writer.writeTextElement(QStringLiteral("receiver"), m_receiver);
+ writer.writeTextElement(u"receiver"_s, m_receiver);
if (m_children & Slot)
- writer.writeTextElement(QStringLiteral("slot"), m_slot);
+ writer.writeTextElement(u"slot"_s, m_slot);
if (m_children & Hints)
- m_hints->write(writer, QStringLiteral("hints"));
+ m_hints->write(writer, u"hints"_s);
writer.writeEndElement();
}
@@ -5837,13 +5851,13 @@ void DomConnectionHints::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("hint"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"hint"_s, Qt::CaseInsensitive)) {
auto *v = new DomConnectionHint();
v->read(reader);
m_hint.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -5859,7 +5873,7 @@ void DomConnectionHints::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connectionhints") : tagName.toLower());
for (DomConnectionHint *v : m_hint)
- v->write(writer, QStringLiteral("hint"));
+ v->write(writer, u"hint"_s);
writer.writeEndElement();
}
@@ -5877,26 +5891,26 @@ void DomConnectionHint::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("type")) {
+ if (name == u"type"_s) {
setAttributeType(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"x"_s, Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toInt());
continue;
}
- if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"y"_s, Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toInt());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -5912,13 +5926,13 @@ void DomConnectionHint::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connectionhint") : tagName.toLower());
if (hasAttributeType())
- writer.writeAttribute(QStringLiteral("type"), attributeType());
+ writer.writeAttribute(u"type"_s, attributeType());
if (m_children & X)
- writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
+ writer.writeTextElement(u"x"_s, QString::number(m_x));
if (m_children & Y)
- writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
+ writer.writeTextElement(u"y"_s, QString::number(m_y));
writer.writeEndElement();
}
@@ -5957,13 +5971,13 @@ void DomDesignerData::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"property"_s, Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -5979,7 +5993,7 @@ void DomDesignerData::write(QXmlStreamWriter &writer, const QString &tagName) co
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("designerdata") : tagName.toLower());
for (DomProperty *v : m_property)
- v->write(writer, QStringLiteral("property"));
+ v->write(writer, u"property"_s);
writer.writeEndElement();
}
@@ -6002,15 +6016,15 @@ void DomSlots::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("signal"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"signal"_s, Qt::CaseInsensitive)) {
m_signal.append(reader.readElementText());
continue;
}
- if (!tag.compare(QLatin1String("slot"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"slot"_s, Qt::CaseInsensitive)) {
m_slot.append(reader.readElementText());
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -6026,10 +6040,10 @@ void DomSlots::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("slots") : tagName.toLower());
for (const QString &v : m_signal)
- writer.writeTextElement(QStringLiteral("signal"), v);
+ writer.writeTextElement(u"signal"_s, v);
for (const QString &v : m_slot)
- writer.writeTextElement(QStringLiteral("slot"), v);
+ writer.writeTextElement(u"slot"_s, v);
writer.writeEndElement();
}
@@ -6060,19 +6074,19 @@ void DomPropertySpecifications::read(QXmlStreamReader &reader)
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- if (!tag.compare(QLatin1String("tooltip"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"tooltip"_s, Qt::CaseInsensitive)) {
auto *v = new DomPropertyToolTip();
v->read(reader);
m_tooltip.append(v);
continue;
}
- if (!tag.compare(QLatin1String("stringpropertyspecification"), Qt::CaseInsensitive)) {
+ if (!tag.compare(u"stringpropertyspecification"_s, Qt::CaseInsensitive)) {
auto *v = new DomStringPropertySpecification();
v->read(reader);
m_stringpropertyspecification.append(v);
continue;
}
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -6088,10 +6102,10 @@ void DomPropertySpecifications::write(QXmlStreamWriter &writer, const QString &t
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("propertyspecifications") : tagName.toLower());
for (DomPropertyToolTip *v : m_tooltip)
- v->write(writer, QStringLiteral("tooltip"));
+ v->write(writer, u"tooltip"_s);
for (DomStringPropertySpecification *v : m_stringpropertyspecification)
- v->write(writer, QStringLiteral("stringpropertyspecification"));
+ v->write(writer, u"stringpropertyspecification"_s);
writer.writeEndElement();
}
@@ -6115,18 +6129,18 @@ void DomPropertyToolTip::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -6142,7 +6156,7 @@ void DomPropertyToolTip::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("propertytooltip") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
writer.writeEndElement();
}
@@ -6154,26 +6168,26 @@ void DomStringPropertySpecification::read(QXmlStreamReader &reader)
const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
const auto name = attribute.name();
- if (name == QLatin1String("name")) {
+ if (name == u"name"_s) {
setAttributeName(attribute.value().toString());
continue;
}
- if (name == QLatin1String("type")) {
+ if (name == u"type"_s) {
setAttributeType(attribute.value().toString());
continue;
}
- if (name == QLatin1String("notr")) {
+ if (name == u"notr"_s) {
setAttributeNotr(attribute.value().toString());
continue;
}
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
+ reader.raiseError("Unexpected attribute "_L1 + name);
}
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const auto tag = reader.name();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ reader.raiseError("Unexpected element "_L1 + tag);
}
break;
case QXmlStreamReader::EndElement :
@@ -6189,13 +6203,13 @@ void DomStringPropertySpecification::write(QXmlStreamWriter &writer, const QStri
writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("stringpropertyspecification") : tagName.toLower());
if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
+ writer.writeAttribute(u"name"_s, attributeName());
if (hasAttributeType())
- writer.writeAttribute(QStringLiteral("type"), attributeType());
+ writer.writeAttribute(u"type"_s, attributeType());
if (hasAttributeNotr())
- writer.writeAttribute(QStringLiteral("notr"), attributeNotr());
+ writer.writeAttribute(u"notr"_s, attributeNotr());
writer.writeEndElement();
}
diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h
index a5ac51f521..333f7f4e6a 100644
--- a/src/tools/uic/ui4.h
+++ b/src/tools/uic/ui4.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 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) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
//
// W A R N I N G
@@ -1670,6 +1645,16 @@ public:
inline bool hasElementKerning() const { return m_children & Kerning; }
void clearElementKerning();
+ inline QString elementHintingPreference() const { return m_hintingPreference; }
+ void setElementHintingPreference(const QString &a);
+ inline bool hasElementHintingPreference() const { return m_children & HintingPreference; }
+ void clearElementHintingPreference();
+
+ inline QString elementFontWeight() const { return m_fontWeight; }
+ void setElementFontWeight(const QString &a);
+ inline bool hasElementFontWeight() const { return m_children & FontWeight; }
+ void clearElementFontWeight();
+
private:
// child element data
@@ -1684,6 +1669,8 @@ private:
bool m_antialiasing = false;
QString m_styleStrategy;
bool m_kerning = false;
+ QString m_hintingPreference;
+ QString m_fontWeight;
enum Child {
Family = 1,
@@ -1695,7 +1682,9 @@ private:
StrikeOut = 64,
Antialiasing = 128,
StyleStrategy = 256,
- Kerning = 512
+ Kerning = 512,
+ HintingPreference = 1024,
+ FontWeight = 2048
};
};
diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp
index 3601280144..fb0a37d21d 100644
--- a/src/tools/uic/uic.cpp
+++ b/src/tools/uic/uic.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "uic.h"
#include "ui4.h"
@@ -47,6 +22,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Uic::Uic(Driver *d)
: drv(d),
out(d->output()),
@@ -61,9 +38,10 @@ bool Uic::printDependencies()
QString fileName = opt.inputFile;
QFile f;
- if (fileName.isEmpty())
- f.open(stdin, QIODevice::ReadOnly);
- else {
+ if (fileName.isEmpty()) {
+ if (!f.open(stdin, QIODevice::ReadOnly))
+ return false;
+ } else {
f.setFileName(fileName);
if (!f.open(QIODevice::ReadOnly))
return false;
@@ -127,7 +105,7 @@ void Uic::writeCopyrightHeaderCpp(const DomUI *ui) const
static inline bool isCppCommentChar(QChar c)
{
- return c == QLatin1Char('/') || c == QLatin1Char('*');
+ return c == u'/' || c == u'*';
}
static int leadingCppCommentCharCount(QStringView s)
@@ -142,13 +120,13 @@ void Uic::writeCopyrightHeaderPython(const DomUI *ui) const
{
QString comment = ui->elementComment();
if (!comment.isEmpty()) {
- const auto lines = QStringView{comment}.split(QLatin1Char('\n'));
+ const auto lines = QStringView{comment}.split(u'\n');
for (const auto &line : lines) {
if (const int leadingCommentChars = leadingCppCommentCharCount(line)) {
out << language::repeat(leadingCommentChars, '#')
<< line.right(line.size() - leadingCommentChars);
} else {
- if (!line.startsWith(QLatin1Char('#')))
+ if (!line.startsWith(u'#'))
out << "# ";
out << line;
}
@@ -169,7 +147,7 @@ void Uic::writeCopyrightHeaderPython(const DomUI *ui) const
static double versionFromUiAttribute(QXmlStreamReader &reader)
{
const QXmlStreamAttributes attributes = reader.attributes();
- const QString versionAttribute = QLatin1String("version");
+ const auto versionAttribute = "version"_L1;
if (!attributes.hasAttribute(versionAttribute))
return 4.0;
const QStringView version = attributes.value(versionAttribute);
@@ -180,7 +158,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
{
DomUI *ui = nullptr;
- const QString uiElement = QLatin1String("ui");
+ const auto uiElement = "ui"_L1;
while (!reader.atEnd()) {
if (reader.readNext() == QXmlStreamReader::StartElement) {
if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0
@@ -195,7 +173,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
ui = new DomUI();
ui->read(reader);
} else {
- reader.raiseError(QLatin1String("Unexpected element ") + reader.name().toString());
+ reader.raiseError("Unexpected element "_L1 + reader.name().toString());
}
}
}
@@ -231,7 +209,7 @@ bool Uic::write(QIODevice *in)
const QString &language = ui->attributeLanguage();
driver()->setUseIdBasedTranslations(ui->attributeIdbasedtr());
- if (!language.isEmpty() && language.compare(QLatin1String("c++"), Qt::CaseInsensitive) != 0) {
+ if (!language.isEmpty() && language.compare("c++"_L1, Qt::CaseInsensitive) != 0) {
fprintf(stderr, "uic: File is not a \"c++\" ui file, language=%s\n", qPrintable(language));
return false;
}
@@ -266,8 +244,7 @@ bool Uic::write(DomUI *ui)
}
pixFunction = ui->elementPixmapFunction();
- if (pixFunction == QLatin1String("QPixmap::fromMimeSource")
- || pixFunction == QLatin1String("qPixmapFromMimeSource")) {
+ if (pixFunction == "QPixmap::fromMimeSource"_L1 || pixFunction == "qPixmapFromMimeSource"_L1) {
fprintf(stderr, "%s: Warning: Obsolete pixmap function '%s' specified in the UI file.\n",
qPrintable(opt.messagePrefix()), qPrintable(pixFunction));
pixFunction.clear();
@@ -315,9 +292,9 @@ void Uic::writeHeaderProtectionEnd()
bool Uic::isButton(const QString &className) const
{
static const QStringList buttons = {
- QLatin1String("QRadioButton"), QLatin1String("QToolButton"),
- QLatin1String("QCheckBox"), QLatin1String("QPushButton"),
- QLatin1String("QCommandLinkButton")
+ u"QRadioButton"_s, u"QToolButton"_s,
+ u"QCheckBox"_s, u"QPushButton"_s,
+ u"QCommandLinkButton"_s
};
return customWidgetsInfo()->extendsOneOf(className, buttons);
}
@@ -325,10 +302,10 @@ bool Uic::isButton(const QString &className) const
bool Uic::isContainer(const QString &className) const
{
static const QStringList containers = {
- QLatin1String("QStackedWidget"), QLatin1String("QToolBox"),
- QLatin1String("QTabWidget"), QLatin1String("QScrollArea"),
- QLatin1String("QMdiArea"), QLatin1String("QWizard"),
- QLatin1String("QDockWidget")
+ u"QStackedWidget"_s, u"QToolBox"_s,
+ u"QTabWidget"_s, u"QScrollArea"_s,
+ u"QMdiArea"_s, u"QWizard"_s,
+ u"QDockWidget"_s
};
return customWidgetsInfo()->extendsOneOf(className, containers);
@@ -337,7 +314,7 @@ bool Uic::isContainer(const QString &className) const
bool Uic::isMenu(const QString &className) const
{
static const QStringList menus = {
- QLatin1String("QMenu"), QLatin1String("QPopupMenu")
+ u"QMenu"_s, u"QPopupMenu"_s
};
return customWidgetsInfo()->extendsOneOf(className, menus);
}
diff --git a/src/tools/uic/uic.h b/src/tools/uic/uic.h
index f3dfd49149..ef5f0a90bd 100644
--- a/src/tools/uic/uic.h
+++ b/src/tools/uic/uic.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef UIC_H
#define UIC_H
diff --git a/src/tools/uic/utils.h b/src/tools/uic/utils.h
index 34c4ab23d4..37247cdea6 100644
--- a/src/tools/uic/utils.h
+++ b/src/tools/uic/utils.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef UTILS_H
#define UTILS_H
@@ -37,7 +12,7 @@
QT_BEGIN_NAMESPACE
inline bool toBool(const QString &str)
-{ return str.toLower() == QLatin1String("true"); }
+{ return QString::compare(str, QLatin1StringView("true"), Qt::CaseInsensitive) == 0; }
inline QString toString(const DomString *str)
{ return str ? str->text() : QString(); }
diff --git a/src/tools/uic/validator.cpp b/src/tools/uic/validator.cpp
index d3b1300ee7..c9f8c0a496 100644
--- a/src/tools/uic/validator.cpp
+++ b/src/tools/uic/validator.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "validator.h"
#include "driver.h"
diff --git a/src/tools/uic/validator.h b/src/tools/uic/validator.h
index f7f7401991..6f965b84d5 100644
--- a/src/tools/uic/validator.h
+++ b/src/tools/uic/validator.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef VALIDATOR_H
#define VALIDATOR_H
diff --git a/src/tools/windeployqt/CMakeLists.txt b/src/tools/windeployqt/CMakeLists.txt
index a63af56efb..2e50116484 100644
--- a/src/tools/windeployqt/CMakeLists.txt
+++ b/src/tools/windeployqt/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#####################################################################
## windeployqt Tool:
#####################################################################
@@ -6,16 +9,19 @@ qt_get_tool_target_name(target_name windeployqt)
qt_internal_add_tool(${target_name}
TOOLS_TARGET Core
USER_FACING
+ INSTALL_VERSIONED_LINK
TARGET_DESCRIPTION "Qt Windows Deployment Tool"
SOURCES
- elfreader.cpp elfreader.h
qmlutils.cpp qmlutils.h
+ qtmoduleinfo.cpp qtmoduleinfo.h
+ qtplugininfo.cpp qtplugininfo.h
utils.cpp utils.h
main.cpp
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_FOREACH
+ QT_NO_QPAIR
LIBRARIES
Qt::CorePrivate
)
@@ -25,8 +31,3 @@ qt_internal_extend_target(${target_name} CONDITION WIN32
PUBLIC_LIBRARIES
shlwapi
)
-
-qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_relocatable
- DEFINES
- QT_RELOCATABLE
-)
diff --git a/src/tools/windeployqt/elfreader.cpp b/src/tools/windeployqt/elfreader.cpp
deleted file mode 100644
index f375f5841d..0000000000
--- a/src/tools/windeployqt/elfreader.cpp
+++ /dev/null
@@ -1,440 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
-
-#include "elfreader.h"
-
-#include <QDir>
-
-QT_BEGIN_NAMESPACE
-
-/* This is a copy of the ELF reader contained in Qt Creator (src/libs/utils),
- * extended by the dependencies() function to read out the dependencies of a dynamic executable. */
-
-quint16 getHalfWord(const unsigned char *&s, const ElfData &context)
-{
- quint16 res;
- if (context.endian == Elf_ELFDATA2MSB)
- res = qFromBigEndian<quint16>(s);
- else
- res = qFromLittleEndian<quint16>(s);
- s += 2;
- return res;
-}
-
-quint32 getWord(const unsigned char *&s, const ElfData &context)
-{
- quint32 res;
- if (context.endian == Elf_ELFDATA2MSB)
- res = qFromBigEndian<quint32>(s);
- else
- res = qFromLittleEndian<quint32>(s);
- s += 4;
- return res;
-}
-
-quint64 getAddress(const unsigned char *&s, const ElfData &context)
-{
- quint64 res;
- if (context.elfclass == Elf_ELFCLASS32) {
- if (context.endian == Elf_ELFDATA2MSB)
- res = qFromBigEndian<quint32>(s);
- else
- res = qFromLittleEndian<quint32>(s);
- s += 4;
- } else {
- if (context.endian == Elf_ELFDATA2MSB)
- res = qFromBigEndian<quint64>(s);
- else
- res = qFromLittleEndian<quint64>(s);
- s += 8;
- }
- return res;
-}
-
-quint64 getOffset(const unsigned char *&s, const ElfData &context)
-{
- return getAddress(s, context);
-}
-
-static void parseSectionHeader(const uchar *s, ElfSectionHeader *sh, const ElfData &context)
-{
- sh->index = getWord(s, context);
- sh->type = getWord(s, context);
- sh->flags = quint32(getOffset(s, context));
- sh->addr = getAddress(s, context);
- sh->offset = getOffset(s, context);
- sh->size = getOffset(s, context);
-}
-
-static void parseProgramHeader(const uchar *s, ElfProgramHeader *sh, const ElfData &context)
-{
- sh->type = getWord(s, context);
- sh->offset = getOffset(s, context);
- /* p_vaddr = */ getAddress(s, context);
- /* p_paddr = */ getAddress(s, context);
- sh->filesz = getWord(s, context);
- sh->memsz = getWord(s, context);
-}
-
-class ElfMapper
-{
-public:
- ElfMapper(const ElfReader *reader) : file(reader->m_binary) {}
-
- bool map()
- {
- if (!file.open(QIODevice::ReadOnly))
- return false;
-
- fdlen = quint64(file.size());
- ustart = file.map(0, qint64(fdlen));
- if (ustart == 0) {
- // Try reading the data into memory instead.
- raw = file.readAll();
- start = raw.constData();
- fdlen = quint64(raw.size());
- }
- return true;
- }
-
-public:
- QFile file;
- QByteArray raw;
- union { const char *start; const uchar *ustart; };
- quint64 fdlen;
-};
-
-ElfReader::ElfReader(const QString &binary)
- : m_binary(binary)
-{
-}
-
-ElfData ElfReader::readHeaders()
-{
- readIt();
- return m_elfData;
-}
-
-static inline QString msgInvalidElfObject(const QString &binary, const QString &why)
-{
- return QStringLiteral("'%1' is an invalid ELF object (%2)")
- .arg(QDir::toNativeSeparators(binary), why);
-}
-
-ElfReader::Result ElfReader::readIt()
-{
- if (!m_elfData.sectionHeaders.isEmpty())
- return Ok;
- if (!m_elfData.programHeaders.isEmpty())
- return Ok;
-
- ElfMapper mapper(this);
- if (!mapper.map())
- return Corrupt;
-
- const quint64 fdlen = mapper.fdlen;
-
- if (fdlen < 64) {
- m_errorString = QStringLiteral("'%1' is not an ELF object (file too small)").arg(QDir::toNativeSeparators(m_binary));
- return NotElf;
- }
-
- if (strncmp(mapper.start, "\177ELF", 4) != 0) {
- m_errorString = QStringLiteral("'%1' is not an ELF object").arg(QDir::toNativeSeparators(m_binary));
- return NotElf;
- }
-
- // 32 or 64 bit
- m_elfData.elfclass = ElfClass(mapper.start[4]);
- const bool is64Bit = m_elfData.elfclass == Elf_ELFCLASS64;
- if (m_elfData.elfclass != Elf_ELFCLASS32 && m_elfData.elfclass != Elf_ELFCLASS64) {
- m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("odd cpu architecture"));
- return Corrupt;
- }
-
- // int bits = (data[4] << 5);
- // If you remove this check to read ELF objects of a different arch,
- // please make sure you modify the typedefs
- // to match the _plugin_ architecture.
- // if ((sizeof(void*) == 4 && bits != 32)
- // || (sizeof(void*) == 8 && bits != 64)) {
- // if (errorString)
- // *errorString = QLibrary::QStringLiteral("'%1' is an invalid ELF object (%2)")
- // .arg(m_binary).arg(QLatin1String("wrong cpu architecture"));
- // return Corrupt;
- // }
-
- // Read Endianhness.
- m_elfData.endian = ElfEndian(mapper.ustart[5]);
- if (m_elfData.endian != Elf_ELFDATA2LSB && m_elfData.endian != Elf_ELFDATA2MSB) {
- m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("odd endianness"));
- return Corrupt;
- }
-
- const uchar *data = mapper.ustart + 16; // e_ident
- m_elfData.elftype = ElfType(getHalfWord(data, m_elfData));
- m_elfData.elfmachine = ElfMachine(getHalfWord(data, m_elfData));
- /* e_version = */ getWord(data, m_elfData);
- m_elfData.entryPoint = getAddress(data, m_elfData);
-
- quint64 e_phoff = getOffset(data, m_elfData);
- quint64 e_shoff = getOffset(data, m_elfData);
- /* e_flags = */ getWord(data, m_elfData);
-
- quint32 e_shsize = getHalfWord(data, m_elfData);
-
- if (e_shsize > fdlen) {
- m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("unexpected e_shsize"));
- return Corrupt;
- }
-
- quint32 e_phentsize = getHalfWord(data, m_elfData);
- if (e_phentsize != (is64Bit ? 56 : 32)) {
- m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("invalid structure"));
- return ElfReader::Corrupt;
- }
- quint32 e_phnum = getHalfWord(data, m_elfData);
-
- quint32 e_shentsize = getHalfWord(data, m_elfData);
-
- if (e_shentsize % 4) {
- m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("unexpected e_shentsize"));
- return Corrupt;
- }
-
- quint32 e_shnum = getHalfWord(data, m_elfData);
- quint32 e_shtrndx = getHalfWord(data, m_elfData);
- if (data != mapper.ustart + (is64Bit ? 64 : 52)) {
- m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("unexpected e_phentsize"));
- return ElfReader::Corrupt;
- }
-
- if (quint64(e_shnum) * e_shentsize > fdlen) {
- const QString reason = QStringLiteral("announced %1 sections, each %2 bytes, exceed file size").arg(e_shnum).arg(e_shentsize);
- m_errorString = msgInvalidElfObject(m_binary, reason);
- return Corrupt;
- }
-
- quint64 soff = e_shoff + e_shentsize * e_shtrndx;
-
-// if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) {
-// m_errorString = QLibrary::QStringLiteral("'%1' is an invalid ELF object (%2)")
-// .arg(m_binary)
-// .arg(QLatin1String("shstrtab section header seems to be at %1"))
-// .arg(QString::number(soff, 16));
-// return Corrupt;
-// }
-
- if (e_shoff) {
- ElfSectionHeader strtab;
- parseSectionHeader(mapper.ustart + soff, &strtab, m_elfData);
- const quint64 stringTableFileOffset = strtab.offset;
- if (quint32(stringTableFileOffset + e_shentsize) >= fdlen
- || stringTableFileOffset == 0) {
- const QString reason = QStringLiteral("string table seems to be at 0x%1").arg(soff, 0, 16);
- m_errorString = msgInvalidElfObject(m_binary, reason);
- return Corrupt;
- }
-
- for (quint32 i = 0; i < e_shnum; ++i) {
- const uchar *s = mapper.ustart + e_shoff + i * e_shentsize;
- ElfSectionHeader sh;
- parseSectionHeader(s, &sh, m_elfData);
-
- if (stringTableFileOffset + sh.index > fdlen) {
- const QString reason = QStringLiteral("section name %1 of %2 behind end of file")
- .arg(i).arg(e_shnum);
- m_errorString = msgInvalidElfObject(m_binary, reason);
- return Corrupt;
- }
-
- sh.name = mapper.start + stringTableFileOffset + sh.index;
- if (sh.name == ".gdb_index") {
- m_elfData.symbolsType = FastSymbols;
- } else if (sh.name == ".debug_info") {
- m_elfData.symbolsType = PlainSymbols;
- } else if (sh.name == ".gnu_debuglink") {
- m_elfData.debugLink = QByteArray(mapper.start + sh.offset);
- m_elfData.symbolsType = LinkedSymbols;
- } else if (sh.name == ".note.gnu.build-id") {
- m_elfData.symbolsType = BuildIdSymbols;
- if (sh.size > 16)
- m_elfData.buildId = QByteArray(mapper.start + sh.offset + 16,
- int(sh.size) - 16).toHex();
- }
- m_elfData.sectionHeaders.append(sh);
- }
- }
-
- if (e_phoff) {
- for (quint32 i = 0; i < e_phnum; ++i) {
- const uchar *s = mapper.ustart + e_phoff + i * e_phentsize;
- ElfProgramHeader ph;
- parseProgramHeader(s, &ph, m_elfData);
- m_elfData.programHeaders.append(ph);
- }
- }
- return Ok;
-}
-
-QByteArray ElfReader::readSection(const QByteArray &name)
-{
- readIt();
- int i = m_elfData.indexOf(name);
- if (i == -1)
- return QByteArray();
-
- ElfMapper mapper(this);
- if (!mapper.map())
- return QByteArray();
-
- const ElfSectionHeader &section = m_elfData.sectionHeaders.at(i);
- return QByteArray(mapper.start + section.offset, int(section.size));
-}
-
-static QByteArray cutout(const char *s)
-{
- QByteArray res(s, 80);
- const int pos = res.indexOf('\0');
- if (pos != -1)
- res.resize(pos - 1);
- return res;
-}
-
-QByteArray ElfReader::readCoreName(bool *isCore)
-{
- *isCore = false;
-
- readIt();
-
- ElfMapper mapper(this);
- if (!mapper.map())
- return QByteArray();
-
- if (m_elfData.elftype != Elf_ET_CORE)
- return QByteArray();
-
- *isCore = true;
-
- for (int i = 0, n = m_elfData.sectionHeaders.size(); i != n; ++i)
- if (m_elfData.sectionHeaders.at(i).type == Elf_SHT_NOTE) {
- const ElfSectionHeader &header = m_elfData.sectionHeaders.at(i);
- return cutout(mapper.start + header.offset + 0x40);
- }
-
- for (int i = 0, n = m_elfData.programHeaders.size(); i != n; ++i)
- if (m_elfData.programHeaders.at(i).type == Elf_PT_NOTE) {
- const ElfProgramHeader &header = m_elfData.programHeaders.at(i);
- return cutout(mapper.start + header.offset + 0xec);
- }
-
- return QByteArray();
-}
-
-int ElfData::indexOf(const QByteArray &name) const
-{
- for (int i = 0, n = sectionHeaders.size(); i != n; ++i)
- if (sectionHeaders.at(i).name == name)
- return i;
- return -1;
-}
-
-/* Helpers for reading out the .dynamic section containing the dependencies.
- * The ".dynamic" section is an array of
- * typedef struct {
- * Elf32_Sword d_tag;
- * union {
- * Elf32_Word d_val;
- * dElf32_Addr d_ptr;
- * } d_un;
- * } Elf32_Dyn
- * with entries where a tag DT_NEEDED indicates that m_val is an offset into
- * the string table ".dynstr". The documentation states that entries with the
- * tag DT_STRTAB contain an offset for the string table to be used, but that
- * has been found not to contain valid entries. */
-
-enum DynamicSectionTags {
- DT_NULL = 0,
- DT_NEEDED = 1,
- DT_STRTAB = 5,
- DT_SONAME = 14,
- DT_RPATH = 15
-};
-
-QList<QByteArray> ElfReader::dependencies()
-{
- QList<QByteArray> result;
-
- ElfMapper mapper(this);
- if (!mapper.map()) {
- m_errorString = QStringLiteral("Mapper failure");
- return result;
- }
- quint64 dynStrOffset = 0;
- quint64 dynamicOffset = 0;
- quint64 dynamicSize = 0;
-
- const QList<ElfSectionHeader> &headers = readHeaders().sectionHeaders;
- for (const ElfSectionHeader &eh : headers) {
- if (eh.name == QByteArrayLiteral(".dynstr")) {
- dynStrOffset = eh.offset;
- } else if (eh.name == QByteArrayLiteral(".dynamic")) {
- dynamicOffset = eh.offset;
- dynamicSize = eh.size;
- }
- if (dynStrOffset && dynamicOffset)
- break;
- }
-
- if (!dynStrOffset || !dynamicOffset) {
- m_errorString = QStringLiteral("Not a dynamically linked executable.");
- return result;
- }
-
- const unsigned char *dynamicData = mapper.ustart + dynamicOffset;
- const unsigned char *dynamicDataEnd = dynamicData + dynamicSize;
- while (dynamicData < dynamicDataEnd) {
- const quint32 tag = getWord(dynamicData, m_elfData);
- if (tag == DT_NULL)
- break;
- if (m_elfData.elfclass == Elf_ELFCLASS64)
- dynamicData += sizeof(quint32); // padding to d_val/d_ptr.
- if (tag == DT_NEEDED) {
- const quint32 offset = getWord(dynamicData, m_elfData);
- if (m_elfData.elfclass == Elf_ELFCLASS64)
- dynamicData += sizeof(quint32); // past d_ptr.
- const char *name = mapper.start + dynStrOffset + offset;
- result.push_back(name);
- } else {
- dynamicData += m_elfData.elfclass == Elf_ELFCLASS64 ? 8 : 4;
- }
- }
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/tools/windeployqt/elfreader.h b/src/tools/windeployqt/elfreader.h
deleted file mode 100644
index d84f5a0602..0000000000
--- a/src/tools/windeployqt/elfreader.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
-
-#ifndef ELFREADER_H
-#define ELFREADER_H
-
-#include <QtCore/QList>
-#include <QtCore/QString>
-#include <QtCore/QtEndian>
-
-QT_BEGIN_NAMESPACE
-
-enum ElfProgramHeaderType
-{
- Elf_PT_NULL = 0,
- Elf_PT_LOAD = 1,
- Elf_PT_DYNAMIC = 2,
- Elf_PT_INTERP = 3,
- Elf_PT_NOTE = 4,
- Elf_PT_SHLIB = 5,
- Elf_PT_PHDR = 6,
- Elf_PT_TLS = 7,
- Elf_PT_NUM = 8
-};
-
-enum ElfSectionHeaderType
-{
- Elf_SHT_NULL = 0,
- Elf_SHT_PROGBITS = 1,
- Elf_SHT_SYMTAB = 2,
- Elf_SHT_STRTAB = 3,
- Elf_SHT_RELA = 4,
- Elf_SHT_HASH = 5,
- Elf_SHT_DYNAMIC = 6,
- Elf_SHT_NOTE = 7,
- Elf_SHT_NOBITS = 8,
- Elf_SHT_REL = 9,
- Elf_SHT_SHLIB = 10,
- Elf_SHT_DYNSYM = 11,
- Elf_SHT_INIT_ARRAY = 14,
- Elf_SHT_FINI_ARRAY = 15,
- Elf_SHT_PREINIT_ARRAY = 16,
- Elf_SHT_GROUP = 17,
- Elf_SHT_SYMTAB_SHNDX = 18
-};
-
-enum ElfEndian
-{
- Elf_ELFDATANONE = 0,
- Elf_ELFDATA2LSB = 1,
- Elf_ELFDATA2MSB = 2,
- Elf_ELFDATANUM = 3
-};
-
-enum ElfClass
-{
- Elf_ELFCLASS32 = 1,
- Elf_ELFCLASS64 = 2
-};
-
-enum ElfType
-{
- Elf_ET_NONE = 0,
- Elf_ET_REL = 1,
- Elf_ET_EXEC = 2,
- Elf_ET_DYN = 3,
- Elf_ET_CORE = 4
-};
-
-enum ElfMachine
-{
- Elf_EM_386 = 3,
- Elf_EM_ARM = 40,
- Elf_EM_X86_64 = 62
-};
-
-enum DebugSymbolsType
-{
- UnknownSymbols = 0, // Unknown.
- NoSymbols = 1, // No usable symbols.
- LinkedSymbols = 2, // Link to symols available.
- BuildIdSymbols = 4, // BuildId available.
- PlainSymbols = 8, // Ordinary symbols available.
- FastSymbols = 16 // Dwarf index available.
-};
-
-class ElfSectionHeader
-{
-public:
- QByteArray name;
- quint32 index;
- quint32 type;
- quint32 flags;
- quint64 offset;
- quint64 size;
- quint64 addr;
-};
-
-class ElfProgramHeader
-{
-public:
- quint32 name;
- quint32 type;
- quint64 offset;
- quint64 filesz;
- quint64 memsz;
-};
-
-class ElfData
-{
-public:
- ElfData() : symbolsType(UnknownSymbols) {}
- int indexOf(const QByteArray &name) const;
-
-public:
- ElfEndian endian;
- ElfType elftype;
- ElfMachine elfmachine;
- ElfClass elfclass;
- quint64 entryPoint;
- QByteArray debugLink;
- QByteArray buildId;
- DebugSymbolsType symbolsType;
- QList<ElfSectionHeader> sectionHeaders;
- QList<ElfProgramHeader> programHeaders;
-};
-
-class ElfReader
-{
-public:
- explicit ElfReader(const QString &binary);
- enum Result { Ok, NotElf, Corrupt };
-
- ElfData readHeaders();
- QByteArray readSection(const QByteArray &sectionName);
- QString errorString() const { return m_errorString; }
- QByteArray readCoreName(bool *isCore);
- QList<QByteArray> dependencies();
-
-private:
- friend class ElfMapper;
- Result readIt();
-
- QString m_binary;
- QString m_errorString;
- ElfData m_elfData;
-};
-
-QT_END_NAMESPACE
-
-#endif // ELFREADER_H
diff --git a/src/tools/windeployqt/main.cpp b/src/tools/windeployqt/main.cpp
index 27b57ea9ad..837d4c7bbc 100644
--- a/src/tools/windeployqt/main.cpp
+++ b/src/tools/windeployqt/main.cpp
@@ -1,33 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "utils.h"
#include "qmlutils.h"
+#include "qtmoduleinfo.h"
+#include "qtplugininfo.h"
#include <QtCore/QCommandLineOption>
#include <QtCore/QCommandLineParser>
@@ -47,152 +24,107 @@
#define IMAGE_FILE_MACHINE_ARM64 0xaa64
#endif
+#include <QtCore/private/qconfig_p.h>
+
#include <algorithm>
+#include <cstdio>
#include <iostream>
#include <iterator>
-#include <cstdio>
+#include <unordered_map>
QT_BEGIN_NAMESPACE
-enum QtModule
-#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC)
- : quint64
-#endif
-{
- QtBluetoothModule = 0x0000000000000001,
- QtConcurrentModule = 0x0000000000000002,
- QtCoreModule = 0x0000000000000004,
- QtDeclarativeModule = 0x0000000000000008,
- QtDesignerComponents = 0x0000000000000010,
- QtDesignerModule = 0x0000000000000020,
- QtGuiModule = 0x0000000000000040,
- QtHelpModule = 0x0000000000000080,
- QtMultimediaModule = 0x0000000000000100,
- QtMultimediaWidgetsModule = 0x0000000000000200,
- QtMultimediaQuickModule = 0x0000000000000400,
- QtNetworkModule = 0x0000000000000800,
- QtNfcModule = 0x0000000000001000,
- QtOpenGLModule = 0x0000000000002000,
- QtOpenGLWidgetsModule = 0x0000000000004000,
- QtPositioningModule = 0x0000000000008000,
- QtPrintSupportModule = 0x0000000000010000,
- QtQmlModule = 0x0000000000020000,
- QtQuickModule = 0x0000000000040000,
- QtQuickParticlesModule = 0x0000000000080000,
- QtScriptModule = 0x0000000000100000,
- QtScriptToolsModule = 0x0000000000200000,
- QtSensorsModule = 0x0000000000400000,
- QtSerialPortModule = 0x0000000000800000,
- QtSqlModule = 0x0000000001000000,
- QtSvgModule = 0x0000000002000000,
- QtSvgWidgetsModule = 0x0000000004000000,
- QtTestModule = 0x0000000008000000,
- QtWidgetsModule = 0x0000000010000000,
- QtWinExtrasModule = 0x0000000020000000,
- QtXmlModule = 0x0000000040000000,
- QtQuickWidgetsModule = 0x0000000100000000,
- QtWebSocketsModule = 0x0000000200000000,
- QtWebEngineCoreModule = 0x0000000800000000,
- QtWebEngineModule = 0x0000001000000000,
- QtWebEngineWidgetsModule = 0x0000002000000000,
- QtQmlToolingModule = 0x0000004000000000,
- Qt3DCoreModule = 0x0000008000000000,
- Qt3DRendererModule = 0x0000010000000000,
- Qt3DQuickModule = 0x0000020000000000,
- Qt3DQuickRendererModule = 0x0000040000000000,
- Qt3DInputModule = 0x0000080000000000,
- QtLocationModule = 0x0000100000000000,
- QtWebChannelModule = 0x0000200000000000,
- QtTextToSpeechModule = 0x0000400000000000,
- QtSerialBusModule = 0x0000800000000000,
- QtGamePadModule = 0x0001000000000000,
- Qt3DAnimationModule = 0x0002000000000000,
- QtWebViewModule = 0x0004000000000000,
- Qt3DExtrasModule = 0x0008000000000000,
- QtShaderToolsModule = 0x0010000000000000
-};
+using namespace Qt::StringLiterals;
-struct QtModuleEntry {
- quint64 module;
- const char *option;
- const char *libraryName;
- const char *translation;
-};
+static QtModuleInfoStore qtModuleEntries;
-static QtModuleEntry qtModuleEntries[] = {
- { QtBluetoothModule, "bluetooth", "Qt6Bluetooth", nullptr },
- { QtConcurrentModule, "concurrent", "Qt6Concurrent", "qtbase" },
- { QtCoreModule, "core", "Qt6Core", "qtbase" },
- { QtDeclarativeModule, "declarative", "Qt6Declarative", "qtquick1" },
- { QtDesignerModule, "designer", "Qt6Designer", nullptr },
- { QtDesignerComponents, "designercomponents", "Qt6DesignerComponents", nullptr },
- { QtGamePadModule, "gamepad", "Qt6Gamepad", nullptr },
- { QtGuiModule, "gui", "Qt6Gui", "qtbase" },
- { QtHelpModule, "qthelp", "Qt6Help", "qt_help" },
- { QtMultimediaModule, "multimedia", "Qt6Multimedia", "qtmultimedia" },
- { QtMultimediaWidgetsModule, "multimediawidgets", "Qt6MultimediaWidgets", "qtmultimedia" },
- { QtMultimediaQuickModule, "multimediaquick", "Qt6MultimediaQuick_p", "qtmultimedia" },
- { QtNetworkModule, "network", "Qt6Network", "qtbase" },
- { QtNfcModule, "nfc", "Qt6Nfc", nullptr },
- { QtOpenGLModule, "opengl", "Qt6OpenGL", nullptr },
- { QtOpenGLWidgetsModule, "openglwidgets", "Qt6OpenGLWidgets", nullptr },
- { QtPositioningModule, "positioning", "Qt6Positioning", nullptr },
- { QtPrintSupportModule, "printsupport", "Qt6PrintSupport", nullptr },
- { QtQmlModule, "qml", "Qt6Qml", "qtdeclarative" },
- { QtQmlToolingModule, "qmltooling", "qmltooling", nullptr },
- { QtQuickModule, "quick", "Qt6Quick", "qtdeclarative" },
- { QtQuickParticlesModule, "quickparticles", "Qt6QuickParticles", nullptr },
- { QtQuickWidgetsModule, "quickwidgets", "Qt6QuickWidgets", nullptr },
- { QtScriptModule, "script", "Qt6Script", "qtscript" },
- { QtScriptToolsModule, "scripttools", "Qt6ScriptTools", "qtscript" },
- { QtSensorsModule, "sensors", "Qt6Sensors", nullptr },
- { QtSerialPortModule, "serialport", "Qt6SerialPort", "qtserialport" },
- { QtSqlModule, "sql", "Qt6Sql", "qtbase" },
- { QtSvgModule, "svg", "Qt6Svg", nullptr },
- { QtSvgWidgetsModule, "svgwidgets", "Qt6SvgWidgets", nullptr },
- { QtTestModule, "test", "Qt6Test", "qtbase" },
- { QtWebSocketsModule, "websockets", "Qt6WebSockets", nullptr },
- { QtWidgetsModule, "widgets", "Qt6Widgets", "qtbase" },
- { QtWinExtrasModule, "winextras", "Qt6WinExtras", nullptr },
- { QtXmlModule, "xml", "Qt6Xml", "qtbase" },
- { QtWebEngineCoreModule, "webenginecore", "Qt6WebEngineCore", nullptr },
- { QtWebEngineModule, "webengine", "Qt6WebEngine", "qtwebengine" },
- { QtWebEngineWidgetsModule, "webenginewidgets", "Qt6WebEngineWidgets", nullptr },
- { Qt3DCoreModule, "3dcore", "Qt63DCore", nullptr },
- { Qt3DRendererModule, "3drenderer", "Qt63DRender", nullptr },
- { Qt3DQuickModule, "3dquick", "Qt63DQuick", nullptr },
- { Qt3DQuickRendererModule, "3dquickrenderer", "Qt63DQuickRender", nullptr },
- { Qt3DInputModule, "3dinput", "Qt63DInput", nullptr },
- { Qt3DAnimationModule, "3danimation", "Qt63DAnimation", nullptr },
- { Qt3DExtrasModule, "3dextras", "Qt63DExtras", nullptr },
- { QtLocationModule, "geoservices", "Qt6Location", nullptr },
- { QtWebChannelModule, "webchannel", "Qt6WebChannel", nullptr },
- { QtTextToSpeechModule, "texttospeech", "Qt6TextToSpeech", nullptr },
- { QtSerialBusModule, "serialbus", "Qt6SerialBus", nullptr },
- { QtWebViewModule, "webview", "Qt6WebView", nullptr },
- { QtShaderToolsModule, "shadertools", "Qt6ShaderTools", nullptr }
-};
+#define DECLARE_KNOWN_MODULE(name) \
+ static size_t Qt##name ## ModuleId = QtModule::InvalidId
-enum QtPlugin {
- QtVirtualKeyboardPlugin = 0x1
-};
+DECLARE_KNOWN_MODULE(3DQuick);
+DECLARE_KNOWN_MODULE(Core);
+DECLARE_KNOWN_MODULE(Designer);
+DECLARE_KNOWN_MODULE(DesignerComponents);
+DECLARE_KNOWN_MODULE(Gui);
+DECLARE_KNOWN_MODULE(Qml);
+DECLARE_KNOWN_MODULE(QmlTooling);
+DECLARE_KNOWN_MODULE(Quick);
+DECLARE_KNOWN_MODULE(WebEngineCore);
+DECLARE_KNOWN_MODULE(Widgets);
+
+#define DEFINE_KNOWN_MODULE(name) \
+ m[QLatin1String("Qt6" #name)] = &Qt##name ## ModuleId
+
+static void assignKnownModuleIds()
+{
+ std::unordered_map<QString, size_t *> m;
+ DEFINE_KNOWN_MODULE(3DQuick);
+ DEFINE_KNOWN_MODULE(Core);
+ DEFINE_KNOWN_MODULE(Designer);
+ DEFINE_KNOWN_MODULE(DesignerComponents);
+ DEFINE_KNOWN_MODULE(Gui);
+ DEFINE_KNOWN_MODULE(Qml);
+ DEFINE_KNOWN_MODULE(QmlTooling);
+ DEFINE_KNOWN_MODULE(Quick);
+ DEFINE_KNOWN_MODULE(WebEngineCore);
+ DEFINE_KNOWN_MODULE(Widgets);
+ for (size_t i = 0; i < qtModuleEntries.size(); ++i) {
+ const QtModule &module = qtModuleEntries.moduleById(i);
+ auto it = m.find(module.name);
+ if (it == m.end())
+ continue;
+ *(it->second) = i;
+ }
+}
+
+#undef DECLARE_KNOWN_MODULE
+#undef DEFINE_KNOWN_MODULE
static const char webEngineProcessC[] = "QtWebEngineProcess";
static inline QString webProcessBinary(const char *binaryName, Platform p)
{
- const QString webProcess = QLatin1String(binaryName);
+ const QString webProcess = QLatin1StringView(binaryName);
return (p & WindowsBased) ? webProcess + QStringLiteral(".exe") : webProcess;
}
-static QByteArray formatQtModules(quint64 mask, bool option = false)
+static QString moduleNameToOptionName(const QString &moduleName)
+{
+ QString result = moduleName
+ .mid(3) // strip the "Qt6" prefix
+ .toLower();
+ if (result == u"help"_s)
+ result.prepend("qt"_L1);
+ return result;
+}
+
+static QByteArray formatQtModules(const ModuleBitset &mask, bool option = false)
{
QByteArray result;
for (const auto &qtModule : qtModuleEntries) {
- if (mask & qtModule.module) {
+ if (mask.test(qtModule.id)) {
if (!result.isEmpty())
result.append(' ');
- result.append(option ? qtModule.option : qtModule.libraryName);
+ result.append(option
+ ? moduleNameToOptionName(qtModule.name).toUtf8()
+ : qtModule.name.toUtf8());
+ if (qtModule.internal)
+ result.append("Internal");
+ }
+ }
+ return result;
+}
+
+static QString formatQtPlugins(const PluginInformation &pluginInfo)
+{
+ QString result(u'\n');
+ for (const auto &pair : pluginInfo.typeMap()) {
+ result += pair.first;
+ result += u": \n";
+ for (const QString &plugin : pair.second) {
+ result += u" ";
+ result += plugin;
+ result += u'\n';
}
}
return result;
@@ -200,14 +132,12 @@ static QByteArray formatQtModules(quint64 mask, bool option = false)
static Platform platformFromMkSpec(const QString &xSpec)
{
- if (xSpec == QLatin1String("linux-g++"))
- return Unix;
- if (xSpec.startsWith(QLatin1String("win32-"))) {
- if (xSpec.contains(QLatin1String("clang-g++")))
+ if (xSpec.startsWith("win32-"_L1)) {
+ if (xSpec.contains("clang-g++"_L1))
return WindowsDesktopClangMinGW;
- if (xSpec.contains(QLatin1String("clang-msvc++")))
+ if (xSpec.contains("clang-msvc++"_L1))
return WindowsDesktopClangMsvc;
- return xSpec.contains(QLatin1String("g++")) ? WindowsDesktopMinGW : WindowsDesktopMsvc;
+ return xSpec.contains("g++"_L1) ? WindowsDesktopMinGW : WindowsDesktopMsvc;
}
return UnknownPlatform;
}
@@ -248,12 +178,14 @@ struct Options {
bool quickImports = true;
bool translations = true;
bool systemD3dCompiler = true;
+ bool systemDxc = true;
bool compilerRunTime = false;
- unsigned disabledPlugins = 0;
bool softwareRasterizer = true;
+ bool ffmpeg = true;
+ PluginSelections pluginSelections;
Platform platform = WindowsDesktopMsvc;
- quint64 additionalLibraries = 0;
- quint64 disabledLibraries = 0;
+ ModuleBitset additionalLibraries;
+ ModuleBitset disabledLibraries;
unsigned updateFileFlags = 0;
QStringList qmlDirectories; // Project's QML files.
QStringList qmlImportPaths; // Custom QML module locations.
@@ -263,6 +195,8 @@ struct Options {
QStringList languages;
QString libraryDirectory;
QString pluginDirectory;
+ QString openSslRootDirectory;
+ QString qmlDirectory;
QStringList binaries;
JsonOutput *json = nullptr;
ListOption list = ListNone;
@@ -271,6 +205,8 @@ struct Options {
bool dryRun = false;
bool patchQt = true;
bool ignoreLibraryErrors = false;
+ bool deployInsightTrackerPlugin = false;
+ bool forceOpenSslPlugin = false;
};
// Return binary to be deployed from folder, ignore pre-existing web engine process.
@@ -282,7 +218,7 @@ static inline QString findBinary(const QString &directory, Platform platform)
QDir(QDir::cleanPath(directory)).entryInfoList(nameFilters, QDir::Files | QDir::Executable);
for (const QFileInfo &binaryFi : binaries) {
const QString binary = binaryFi.fileName();
- if (!binary.contains(QLatin1String(webEngineProcessC), Qt::CaseInsensitive)) {
+ if (!binary.contains(QLatin1StringView(webEngineProcessC), Qt::CaseInsensitive)) {
return binaryFi.absoluteFilePath();
}
}
@@ -291,15 +227,101 @@ static inline QString findBinary(const QString &directory, Platform platform)
static QString msgFileDoesNotExist(const QString & file)
{
- return QLatin1Char('"') + QDir::toNativeSeparators(file)
- + QStringLiteral("\" does not exist.");
+ return u'"' + QDir::toNativeSeparators(file) + "\" does not exist."_L1;
}
enum CommandLineParseFlag {
CommandLineParseError = 0x1,
- CommandLineParseHelpRequested = 0x2
+ CommandLineParseHelpRequested = 0x2,
+ CommandLineVersionRequested = 0x4
};
+static QCommandLineOption createQMakeOption()
+{
+ return {
+ u"qmake"_s,
+ u"Use specified qmake instead of qmake from PATH. Deprecated, use qtpaths instead."_s,
+ u"path"_s
+ };
+}
+
+static QCommandLineOption createQtPathsOption()
+{
+ return {
+ u"qtpaths"_s,
+ u"Use specified qtpaths.exe instead of qtpaths.exe from PATH."_s,
+ u"path"_s
+ };
+}
+
+static QCommandLineOption createVerboseOption()
+{
+ return {
+ u"verbose"_s,
+ u"Verbose level (0-2)."_s,
+ u"level"_s
+ };
+}
+
+static int parseEarlyArguments(const QStringList &arguments, Options *options,
+ QString *errorMessage)
+{
+ QCommandLineParser parser;
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+
+ QCommandLineOption qmakeOption = createQMakeOption();
+ parser.addOption(qmakeOption);
+
+ QCommandLineOption qtpathsOption = createQtPathsOption();
+ parser.addOption(qtpathsOption);
+
+ QCommandLineOption verboseOption = createVerboseOption();
+ parser.addOption(verboseOption);
+
+ // Deliberately don't check for errors. We want to ignore options we don't know about.
+ parser.parse(arguments);
+
+ if (parser.isSet(qmakeOption) && parser.isSet(qtpathsOption)) {
+ *errorMessage = QStringLiteral("-qmake and -qtpaths are mutually exclusive.");
+ return CommandLineParseError;
+ }
+
+ if (parser.isSet(qmakeOption) && optVerboseLevel >= 1)
+ std::wcerr << "Warning: -qmake option is deprecated. Use -qtpaths instead.\n";
+
+ if (parser.isSet(qtpathsOption) || parser.isSet(qmakeOption)) {
+ const QString qtpathsArg = parser.isSet(qtpathsOption) ? parser.value(qtpathsOption)
+ : parser.value(qmakeOption);
+
+ const QString qtpathsBinary = QDir::cleanPath(qtpathsArg);
+ const QFileInfo fi(qtpathsBinary);
+ if (!fi.exists()) {
+ *errorMessage = msgFileDoesNotExist(qtpathsBinary);
+ return CommandLineParseError;
+ }
+
+ if (!fi.isExecutable()) {
+ *errorMessage = u'"' + QDir::toNativeSeparators(qtpathsBinary)
+ + QStringLiteral("\" is not an executable.");
+ return CommandLineParseError;
+ }
+ options->qtpathsBinary = qtpathsBinary;
+ }
+
+ if (parser.isSet(verboseOption)) {
+ bool ok;
+ const QString value = parser.value(verboseOption);
+ optVerboseLevel = value.toInt(&ok);
+ if (!ok || optVerboseLevel < 0) {
+ *errorMessage = QStringLiteral("Invalid value \"%1\" passed for verbose level.")
+ .arg(value);
+ return CommandLineParseError;
+ }
+ }
+
+ return 0;
+}
+
static inline int parseArguments(const QStringList &arguments, QCommandLineParser *parser,
Options *options, QString *errorMessage)
{
@@ -307,29 +329,21 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
using OptionPtrVector = QList<CommandLineOptionPtr>;
parser->setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
- parser->setApplicationDescription(QStringLiteral("Qt Deploy Tool ") + QLatin1String(QT_VERSION_STR)
- + QLatin1String("\n\nThe simplest way to use windeployqt is to add the bin directory of your Qt\n"
+ parser->setApplicationDescription(u"Qt Deploy Tool " QT_VERSION_STR
+ "\n\nThe simplest way to use windeployqt is to add the bin directory of your Qt\n"
"installation (e.g. <QT_DIR\\bin>) to the PATH variable and then run:\n windeployqt <path-to-app-binary>\n\n"
- "If your application uses Qt Quick, run:\n windeployqt --qmldir <path-to-app-qml-files> <path-to-app-binary>"));
+ "If your application uses Qt Quick, run:\n windeployqt --qmldir <path-to-app-qml-files> <path-to-app-binary>"_s);
const QCommandLineOption helpOption = parser->addHelpOption();
- parser->addVersionOption();
+ const QCommandLineOption versionOption = parser->addVersionOption();
QCommandLineOption dirOption(QStringLiteral("dir"),
QStringLiteral("Use directory instead of binary directory."),
QStringLiteral("directory"));
parser->addOption(dirOption);
- QCommandLineOption qmakeOption(QStringLiteral("qmake"),
- QStringLiteral("Use specified qmake instead of qmake from PATH. "
- "Deprecated, use qtpaths instead."),
- QStringLiteral("path"));
- parser->addOption(qmakeOption);
-
- QCommandLineOption qtpathsOption(
- QStringLiteral("qtpaths"),
- QStringLiteral("Use specified qtpaths.exe instead of qtpaths.exe from PATH."),
- QStringLiteral("path"));
- parser->addOption(qtpathsOption);
+ // Add early options to have them available in the help text.
+ parser->addOption(createQMakeOption());
+ parser->addOption(createQtPathsOption());
QCommandLineOption libDirOption(QStringLiteral("libdir"),
QStringLiteral("Copy libraries to path."),
@@ -341,6 +355,17 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
QStringLiteral("path"));
parser->addOption(pluginDirOption);
+ const QCommandLineOption translationDirOption(
+ u"translationdir"_s,
+ u"Copy translations to path."_s,
+ u"path"_s);
+ parser->addOption(translationDirOption);
+
+ QCommandLineOption qmlDeployDirOption(QStringLiteral("qml-deploy-dir"),
+ QStringLiteral("Copy qml files to path."),
+ QStringLiteral("path"));
+ parser->addOption(qmlDeployDirOption);
+
QCommandLineOption debugOption(QStringLiteral("debug"),
QStringLiteral("Assume debug binaries."));
parser->addOption(debugOption);
@@ -376,6 +401,30 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
QStringLiteral("Skip plugin deployment."));
parser->addOption(noPluginsOption);
+ QCommandLineOption includeSoftPluginsOption(QStringLiteral("include-soft-plugins"),
+ QStringLiteral("Include in the deployment all relevant plugins by taking into account all soft dependencies."));
+ parser->addOption(includeSoftPluginsOption);
+
+ QCommandLineOption skipPluginTypesOption(QStringLiteral("skip-plugin-types"),
+ QStringLiteral("A comma-separated list of plugin types that are not deployed (qmltooling,generic)."),
+ QStringLiteral("plugin types"));
+ parser->addOption(skipPluginTypesOption);
+
+ QCommandLineOption addPluginTypesOption(QStringLiteral("add-plugin-types"),
+ QStringLiteral("A comma-separated list of plugin types that will be added to deployment (imageformats,iconengines)"),
+ QStringLiteral("plugin types"));
+ parser->addOption(addPluginTypesOption);
+
+ QCommandLineOption includePluginsOption(QStringLiteral("include-plugins"),
+ QStringLiteral("A comma-separated list of individual plugins that will be added to deployment (scene2d,qjpeg)"),
+ QStringLiteral("plugins"));
+ parser->addOption(includePluginsOption);
+
+ QCommandLineOption excludePluginsOption(QStringLiteral("exclude-plugins"),
+ QStringLiteral("A comma-separated list of individual plugins that will not be deployed (qsvg,qpdf)"),
+ QStringLiteral("plugins"));
+ parser->addOption(excludePluginsOption);
+
QCommandLineOption noLibraryOption(QStringLiteral("no-libraries"),
QStringLiteral("Skip library deployment."));
parser->addOption(noLibraryOption);
@@ -408,15 +457,15 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
QStringLiteral("Skip deployment of the system D3D compiler."));
parser->addOption(noSystemD3DCompilerOption);
+ QCommandLineOption noSystemDxcOption(QStringLiteral("no-system-dxc-compiler"),
+ QStringLiteral("Skip deployment of the system DXC (dxcompiler.dll, dxil.dll)."));
+ parser->addOption(noSystemDxcOption);
+
QCommandLineOption compilerRunTimeOption(QStringLiteral("compiler-runtime"),
QStringLiteral("Deploy compiler runtime (Desktop only)."));
parser->addOption(compilerRunTimeOption);
- QCommandLineOption noVirtualKeyboardOption(QStringLiteral("no-virtualkeyboard"),
- QStringLiteral("Disable deployment of the Virtual Keyboard."));
- parser->addOption(noVirtualKeyboardOption);
-
QCommandLineOption noCompilerRunTimeOption(QStringLiteral("no-compiler-runtime"),
QStringLiteral("Do not deploy compiler runtime (Desktop only)."));
parser->addOption(noCompilerRunTimeOption);
@@ -429,8 +478,22 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
QStringLiteral("Do not deploy the software rasterizer library."));
parser->addOption(suppressSoftwareRasterizerOption);
+ QCommandLineOption noFFmpegOption(QStringLiteral("no-ffmpeg"),
+ QStringLiteral("Do not deploy the FFmpeg libraries."));
+ parser->addOption(noFFmpegOption);
+
+ QCommandLineOption forceOpenSslOption(QStringLiteral("force-openssl"),
+ QStringLiteral("Deploy openssl plugin but ignore openssl library dependency"));
+ parser->addOption(forceOpenSslOption);
+
+ QCommandLineOption openSslRootOption(QStringLiteral("openssl-root"),
+ QStringLiteral("Directory containing openSSL libraries."),
+ QStringLiteral("directory"));
+ parser->addOption(openSslRootOption);
+
+
QCommandLineOption listOption(QStringLiteral("list"),
- QLatin1String("Print only the names of the files copied.\n"
+ "Print only the names of the files copied.\n"
"Available options:\n"
" source: absolute path of the source files\n"
" target: absolute path of the target files\n"
@@ -438,26 +501,33 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
" to the target directory\n"
" mapping: outputs the source and the relative\n"
" target, suitable for use within an\n"
- " Appx mapping file"),
+ " Appx mapping file"_L1,
QStringLiteral("option"));
parser->addOption(listOption);
- QCommandLineOption verboseOption(QStringLiteral("verbose"),
- QStringLiteral("Verbose level (0-2)."),
- QStringLiteral("level"));
- parser->addOption(verboseOption);
+ // Add early option to have it available in the help text.
+ parser->addOption(createVerboseOption());
parser->addPositionalArgument(QStringLiteral("[files]"),
QStringLiteral("Binaries or directory containing the binary."));
+ QCommandLineOption deployInsightTrackerOption(QStringLiteral("deploy-insighttracker"),
+ QStringLiteral("Deploy insight tracker plugin."));
+ // The option will be added to the parser if the module is available (see block below)
+ bool insightTrackerModuleAvailable = false;
+
OptionPtrVector enabledModuleOptions;
OptionPtrVector disabledModuleOptions;
- const int qtModulesCount = int(sizeof(qtModuleEntries) / sizeof(QtModuleEntry));
+ const size_t qtModulesCount = qtModuleEntries.size();
enabledModuleOptions.reserve(qtModulesCount);
disabledModuleOptions.reserve(qtModulesCount);
- for (int i = 0; i < qtModulesCount; ++i) {
- const QString option = QLatin1String(qtModuleEntries[i].option);
- const QString name = QLatin1String(qtModuleEntries[i].libraryName);
+ for (const QtModule &module : qtModuleEntries) {
+ const QString option = moduleNameToOptionName(module.name);
+ const QString name = module.name;
+ if (name == u"InsightTracker") {
+ parser->addOption(deployInsightTrackerOption);
+ insightTrackerModuleAvailable = true;
+ }
const QString enabledDescription = QStringLiteral("Add ") + name + QStringLiteral(" module.");
CommandLineOptionPtr enabledOption(new QCommandLineOption(option, enabledDescription));
parser->addOption(*enabledOption.data());
@@ -472,6 +542,8 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
const bool success = parser->parse(arguments);
if (parser->isSet(helpOption))
return CommandLineParseHelpRequested;
+ if (parser->isSet(versionOption))
+ return CommandLineVersionRequested;
if (!success) {
*errorMessage = parser->errorText();
return CommandLineParseError;
@@ -479,12 +551,15 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
options->libraryDirectory = parser->value(libDirOption);
options->pluginDirectory = parser->value(pluginDirOption);
+ options->translationsDirectory = parser->value(translationDirOption);
+ options->qmlDirectory = parser->value(qmlDeployDirOption);
options->plugins = !parser->isSet(noPluginsOption);
options->libraries = !parser->isSet(noLibraryOption);
options->translations = !parser->isSet(noTranslationOption);
if (parser->isSet(translationOption))
- options->languages = parser->value(translationOption).split(QLatin1Char(','));
+ options->languages = parser->value(translationOption).split(u',');
options->systemD3dCompiler = !parser->isSet(noSystemD3DCompilerOption);
+ options->systemDxc = !parser->isSet(noSystemDxcOption);
options->quickImports = !parser->isSet(noQuickImportOption);
// default to deployment of compiler runtime for windows desktop configurations
@@ -499,8 +574,19 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
return CommandLineParseError;
}
- if (parser->isSet(noVirtualKeyboardOption))
- options->disabledPlugins |= QtVirtualKeyboardPlugin;
+ options->pluginSelections.includeSoftPlugins = parser->isSet(includeSoftPluginsOption);
+
+ if (parser->isSet(skipPluginTypesOption))
+ options->pluginSelections.disabledPluginTypes = parser->value(skipPluginTypesOption).split(u',');
+
+ if (parser->isSet(addPluginTypesOption))
+ options->pluginSelections.enabledPluginTypes = parser->value(addPluginTypesOption).split(u',');
+
+ if (parser->isSet(includePluginsOption))
+ options->pluginSelections.includedPlugins = parser->value(includePluginsOption).split(u',');
+
+ if (parser->isSet(excludePluginsOption))
+ options->pluginSelections.excludedPlugins = parser->value(excludePluginsOption).split(u',');
if (parser->isSet(releaseWithDebugInfoOption))
std::wcerr << "Warning: " << releaseWithDebugInfoOption.names().first() << " is obsolete.";
@@ -526,6 +612,20 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
if (parser->isSet(suppressSoftwareRasterizerOption))
options->softwareRasterizer = false;
+ if (parser->isSet(noFFmpegOption))
+ options->ffmpeg = false;
+
+ if (parser->isSet(forceOpenSslOption))
+ options->forceOpenSslPlugin = true;
+
+ if (parser->isSet(openSslRootOption))
+ options->openSslRootDirectory = parser->value(openSslRootOption);
+
+ if (options->forceOpenSslPlugin && !options->openSslRootDirectory.isEmpty()) {
+ *errorMessage = QStringLiteral("force-openssl and openssl-root are mutually exclusive");
+ return CommandLineParseError;
+ }
+
if (parser->isSet(forceOption))
options->updateFileFlags |= ForceUpdateFile;
if (parser->isSet(dryRunOption)) {
@@ -535,19 +635,21 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
options->patchQt = !parser->isSet(noPatchQtOption);
options->ignoreLibraryErrors = parser->isSet(ignoreErrorOption);
-
- for (int i = 0; i < qtModulesCount; ++i) {
- if (parser->isSet(*enabledModuleOptions.at(i)))
- options->additionalLibraries |= qtModuleEntries[i].module;
- if (parser->isSet(*disabledModuleOptions.at(i)))
- options->disabledLibraries |= qtModuleEntries[i].module;
+ if (insightTrackerModuleAvailable)
+ options->deployInsightTrackerPlugin = parser->isSet(deployInsightTrackerOption);
+
+ for (const QtModule &module : qtModuleEntries) {
+ if (parser->isSet(*enabledModuleOptions.at(module.id)))
+ options->additionalLibraries[module.id] = 1;
+ if (parser->isSet(*disabledModuleOptions.at(module.id)))
+ options->disabledLibraries[module.id] = 1;
}
// Add some dependencies
- if (options->additionalLibraries & QtQuickModule)
- options->additionalLibraries |= QtQmlModule;
- if (options->additionalLibraries & QtDesignerComponents)
- options->additionalLibraries |= QtDesignerModule;
+ if (options->additionalLibraries.test(QtQuickModuleId))
+ options->additionalLibraries[QtQmlModuleId] = 1;
+ if (options->additionalLibraries.test(QtDesignerComponentsModuleId))
+ options->additionalLibraries[QtDesignerModuleId] = 1;
if (parser->isSet(listOption)) {
const QString value = parser->value(listOption);
@@ -568,16 +670,6 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
if (parser->isSet(jsonOption) || options->list) {
optVerboseLevel = 0;
options->json = new JsonOutput;
- } else {
- if (parser->isSet(verboseOption)) {
- bool ok;
- const QString value = parser->value(verboseOption);
- optVerboseLevel = value.toInt(&ok);
- if (!ok || optVerboseLevel < 0) {
- *errorMessage = QStringLiteral("Invalid value \"%1\" passed for verbose level.").arg(value);
- return CommandLineParseError;
- }
- }
}
const QStringList posArgs = parser->positionalArguments();
@@ -589,33 +681,6 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
if (parser->isSet(dirOption))
options->directory = parser->value(dirOption);
- if (parser->isSet(qmakeOption) && parser->isSet(qtpathsOption)) {
- *errorMessage = QStringLiteral("-qmake and -qtpaths are mutually exclusive.");
- return CommandLineParseError;
- }
-
- if (parser->isSet(qmakeOption) && optVerboseLevel >= 1)
- std::wcerr << "Warning: -qmake option is deprecated. Use -qpaths instead.\n";
-
- if (parser->isSet(qtpathsOption) || parser->isSet(qmakeOption)) {
- const QString qtpathsArg = parser->isSet(qtpathsOption) ? parser->value(qtpathsOption)
- : parser->value(qmakeOption);
-
- const QString qtpathsBinary = QDir::cleanPath(qtpathsArg);
- const QFileInfo fi(qtpathsBinary);
- if (!fi.exists()) {
- *errorMessage = msgFileDoesNotExist(qtpathsBinary);
- return CommandLineParseError;
- }
-
- if (!fi.isExecutable()) {
- *errorMessage = QLatin1Char('"') + QDir::toNativeSeparators(qtpathsBinary)
- + QStringLiteral("\" is not an executable.");
- return CommandLineParseError;
- }
- options->qtpathsBinary = qtpathsBinary;
- }
-
if (parser->isSet(qmlDirOption))
options->qmlDirectories = parser->values(qmlDirOption);
@@ -630,7 +695,7 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
}
if (!options->directory.isEmpty() && !fi.isFile()) { // -dir was specified - expecting file.
- *errorMessage = QLatin1Char('"') + file + QStringLiteral("\" is not an executable file.");
+ *errorMessage = u'"' + file + QStringLiteral("\" is not an executable file.");
return CommandLineParseError;
}
@@ -641,7 +706,7 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
} else {
const QString binary = findBinary(fi.absoluteFilePath(), options->platform);
if (binary.isEmpty()) {
- *errorMessage = QStringLiteral("Unable to find binary in \"") + file + QLatin1Char('"');
+ *errorMessage = QStringLiteral("Unable to find binary in \"") + file + u'"';
return CommandLineParseError;
}
options->directory = fi.absoluteFilePath();
@@ -649,6 +714,7 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
} // directory.
// Remaining files or plugin directories
+ bool multipleDirs = false;
for (int i = 1; i < posArgs.size(); ++i) {
const QFileInfo fi(QDir::cleanPath(posArgs.at(i)));
const QString path = fi.absoluteFilePath();
@@ -660,42 +726,66 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
const QStringList libraries =
findSharedLibraries(QDir(path), options->platform, MatchDebugOrRelease, QString());
for (const QString &library : libraries)
- options->binaries.append(path + QLatin1Char('/') + library);
+ options->binaries.append(path + u'/' + library);
} else {
+ if (!parser->isSet(dirOption) && fi.absolutePath() != options->directory)
+ multipleDirs = true;
options->binaries.append(path);
}
}
- options->translationsDirectory = options->directory + QLatin1String("/translations");
+ if (multipleDirs) {
+ std::wcerr << "Warning: using binaries from different directories, deploying to following path: "
+ << options->directory << '\n' << "To disable this warning, use the --dir option\n";
+ }
+ if (options->translationsDirectory.isEmpty())
+ options->translationsDirectory = options->directory + "/translations"_L1;
return 0;
}
// Simple line wrapping at 80 character boundaries.
static inline QString lineBreak(QString s)
{
- for (int i = 80; i < s.size(); i += 80) {
- const int lastBlank = s.lastIndexOf(QLatin1Char(' '), i);
+ for (qsizetype i = 80; i < s.size(); i += 80) {
+ const qsizetype lastBlank = s.lastIndexOf(u' ', i);
if (lastBlank >= 0) {
- s[lastBlank] = QLatin1Char('\n');
+ s[lastBlank] = u'\n';
i = lastBlank + 1;
}
}
return s;
}
-static inline QString helpText(const QCommandLineParser &p)
+static inline QString helpText(const QCommandLineParser &p, const PluginInformation &pluginInfo)
{
QString result = p.helpText();
// Replace the default-generated text which is too long by a short summary
// explaining how to enable single libraries.
- const int moduleStart = result.indexOf(QLatin1String("\n --bluetooth"));
- const int argumentsStart = result.lastIndexOf(QLatin1String("\nArguments:"));
+ if (qtModuleEntries.size() == 0)
+ return result;
+ const QtModule &firstModule = qtModuleEntries.moduleById(0);
+ const QString firstModuleOption = moduleNameToOptionName(firstModule.name);
+ const qsizetype moduleStart = result.indexOf("\n --"_L1 + firstModuleOption);
+ const qsizetype argumentsStart = result.lastIndexOf("\nArguments:"_L1);
if (moduleStart >= argumentsStart)
return result;
- QString moduleHelp = QLatin1String(
+ QString moduleHelp;
+ moduleHelp +=
"\n\nQt libraries can be added by passing their name (-xml) or removed by passing\n"
- "the name prepended by --no- (--no-xml). Available libraries:\n");
- moduleHelp += lineBreak(QString::fromLatin1(formatQtModules(0xFFFFFFFFFFFFFFFFull, true)));
- moduleHelp += QLatin1Char('\n');
+ "the name prepended by --no- (--no-xml). Available libraries:\n"_L1;
+ ModuleBitset mask;
+ moduleHelp += lineBreak(QString::fromLatin1(formatQtModules(mask.set(), true)));
+ moduleHelp += u"\n\n";
+ moduleHelp +=
+ u"Qt plugins can be included or excluded individually or by type.\n"
+ u"To deploy or block plugins individually, use the --include-plugins\n"
+ u"and --exclude-plugins options (--include-plugins qjpeg,qsvgicon)\n"
+ u"You can also use the --skip-plugin-types or --add-plugin-types to\n"
+ u"achieve similar results with entire plugin groups, like imageformats, e.g.\n"
+ u"(--add-plugin-types imageformats,iconengines). Exclusion always takes\n"
+ u"precedence over inclusion, and types take precedence over specific plugins.\n"
+ u"For example, including qjpeg, but skipping imageformats, will NOT deploy qjpeg.\n"
+ u"\nDetected available plugins:\n";
+ moduleHelp += formatQtPlugins(pluginInfo);
result.replace(moduleStart, argumentsStart - moduleStart, moduleHelp);
return result;
}
@@ -703,7 +793,7 @@ static inline QString helpText(const QCommandLineParser &p)
static inline bool isQtModule(const QString &libName)
{
// Match Standard modules named Qt6XX.dll
- if (libName.size() < 3 || !libName.startsWith(QLatin1String("Qt"), Qt::CaseInsensitive))
+ if (libName.size() < 3 || !libName.startsWith("Qt"_L1, Qt::CaseInsensitive))
return false;
const QChar version = libName.at(2);
return version.isDigit() && (version.toLatin1() - '0') == QT_VERSION_MAJOR;
@@ -719,17 +809,18 @@ static bool findDependentQtLibraries(const QString &qtBinDir, const QString &bin
QStringList dependentLibs;
if (directDependencyCount)
*directDependencyCount = 0;
- if (!readExecutable(binary, platform, errorMessage, &dependentLibs, wordSize, isDebug, machineArch)) {
- errorMessage->prepend(QLatin1String("Unable to find dependent libraries of ") +
- QDir::toNativeSeparators(binary) + QLatin1String(" :"));
+ if (!readPeExecutable(binary, errorMessage, &dependentLibs, wordSize, isDebug,
+ platform == WindowsDesktopMinGW, machineArch)) {
+ errorMessage->prepend("Unable to find dependent libraries of "_L1 +
+ QDir::toNativeSeparators(binary) + " :"_L1);
return false;
}
// Filter out the Qt libraries. Note that depends.exe finds libs from optDirectory if we
// are run the 2nd time (updating). We want to check against the Qt bin dir libraries
const int start = result->size();
- for (const QString &lib : qAsConst(dependentLibs)) {
+ for (const QString &lib : std::as_const(dependentLibs)) {
if (isQtModule(lib)) {
- const QString path = normalizeFileName(qtBinDir + QLatin1Char('/') + QFileInfo(lib).fileName());
+ const QString path = normalizeFileName(qtBinDir + u'/' + QFileInfo(lib).fileName());
if (!result->contains(path))
result->append(path);
}
@@ -764,10 +855,10 @@ private:
static QString pdbFileName(QString libraryFileName)
{
- const int lastDot = libraryFileName.lastIndexOf(QLatin1Char('.')) + 1;
+ const qsizetype lastDot = libraryFileName.lastIndexOf(u'.') + 1;
if (lastDot <= 0)
return QString();
- libraryFileName.replace(lastDot, libraryFileName.size() - lastDot, QLatin1String("pdb"));
+ libraryFileName.replace(lastDot, libraryFileName.size() - lastDot, "pdb"_L1);
return libraryFileName;
}
static inline QStringList qmlCacheFileFilters()
@@ -776,7 +867,7 @@ static inline QStringList qmlCacheFileFilters()
}
// File entry filter function for updateFile() that returns a list of files for
-// QML import trees: DLLs (matching debgug) and .qml/,js, etc.
+// QML import trees: DLLs (matching debug) and .qml/,js, etc.
class QmlDirectoryFileEntryFunction {
public:
enum Flags {
@@ -784,13 +875,19 @@ public:
SkipSources = 0x2
};
- explicit QmlDirectoryFileEntryFunction(Platform platform, DebugMatchMode debugMatchMode, unsigned flags)
+ explicit QmlDirectoryFileEntryFunction(
+ const QString &moduleSourcePath, Platform platform, DebugMatchMode debugMatchMode, unsigned flags)
: m_flags(flags), m_qmlNameFilter(QmlDirectoryFileEntryFunction::qmlNameFilters(flags))
- , m_dllFilter(platform, debugMatchMode)
+ , m_dllFilter(platform, debugMatchMode), m_moduleSourcePath(moduleSourcePath)
{}
QStringList operator()(const QDir &dir) const
{
+ if (moduleSourceDir(dir).canonicalPath() != m_moduleSourcePath) {
+ // If we're in a different module, return nothing.
+ return {};
+ }
+
QStringList result;
const QStringList &libraries = m_dllFilter(dir);
for (const QString &library : libraries) {
@@ -806,6 +903,17 @@ public:
}
private:
+ static QDir moduleSourceDir(const QDir &dir)
+ {
+ QDir moduleSourceDir = dir;
+ while (!moduleSourceDir.exists(QStringLiteral("qmldir"))) {
+ if (!moduleSourceDir.cdUp()) {
+ return {};
+ }
+ }
+ return moduleSourceDir;
+ }
+
static inline QStringList qmlNameFilters(unsigned flags)
{
QStringList result;
@@ -822,175 +930,216 @@ private:
const unsigned m_flags;
NameFilterFileEntryFunction m_qmlNameFilter;
DllDirectoryFileEntryFunction m_dllFilter;
+ QString m_moduleSourcePath;
};
-struct PluginModuleMapping
-{
- const char *directoryName;
- quint64 module;
-};
-
-static const PluginModuleMapping pluginModuleMappings[] =
-{
- {"qml1tooling", QtDeclarativeModule},
-#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
- {"gamepads", QtGamePadModule},
-#endif
- {"accessible", QtGuiModule},
- {"iconengines", QtGuiModule},
- {"imageformats", QtGuiModule},
- {"platforms", QtGuiModule},
- {"platforminputcontexts", QtGuiModule},
- {"virtualkeyboard", QtGuiModule},
- {"geoservices", QtLocationModule},
- {"audio", QtMultimediaModule},
- {"mediaservice", QtMultimediaModule},
- {"playlistformats", QtMultimediaModule},
- {"networkaccess", QtNetworkModule},
- {"networkinformation", QtNetworkModule},
- {"tls", QtNetworkModule},
- {"position", QtPositioningModule},
- {"printsupport", QtPrintSupportModule},
- {"scenegraph", QtQuickModule},
- {"qmltooling", QtQuickModule | QtQmlToolingModule},
- {"sensors", QtSensorsModule},
- {"sensorgestures", QtSensorsModule},
- {"canbus", QtSerialBusModule},
- {"sqldrivers", QtSqlModule},
-#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
- {"texttospeech", QtTextToSpeechModule},
-#endif
- {"qtwebengine", QtWebEngineModule | QtWebEngineCoreModule | QtWebEngineWidgetsModule},
- {"styles", QtWidgetsModule},
- {"sceneparsers", Qt3DRendererModule},
- {"renderers", Qt3DRendererModule | QtShaderToolsModule},
- {"renderplugins", Qt3DRendererModule},
- {"geometryloaders", Qt3DRendererModule},
- {"webview", QtWebViewModule}
-};
-
-static inline quint64 qtModuleForPlugin(const QString &subDirName)
-{
- const auto end = std::end(pluginModuleMappings);
- const auto result =
- std::find_if(std::begin(pluginModuleMappings), end,
- [&subDirName] (const PluginModuleMapping &m) { return subDirName == QLatin1String(m.directoryName); });
- return result != end ? result->module : 0; // "designer"
-}
-
-static quint64 qtModule(QString module, const QString &infix)
+static qint64 qtModule(QString module, const QString &infix)
{
// Match needle 'path/Qt6Core<infix><d>.dll' or 'path/libQt6Core<infix>.so.5.0'
- const int lastSlashPos = module.lastIndexOf(QLatin1Char('/'));
+ const qsizetype lastSlashPos = module.lastIndexOf(u'/');
if (lastSlashPos > 0)
module.remove(0, lastSlashPos + 1);
- if (module.startsWith(QLatin1String("lib")))
+ if (module.startsWith("lib"_L1))
module.remove(0, 3);
int endPos = infix.isEmpty() ? -1 : module.lastIndexOf(infix);
if (endPos == -1)
- endPos = module.indexOf(QLatin1Char('.')); // strip suffixes '.so.5.0'.
+ endPos = module.indexOf(u'.'); // strip suffixes '.so.5.0'.
if (endPos > 0)
module.truncate(endPos);
// That should leave us with 'Qt6Core<d>'.
for (const auto &qtModule : qtModuleEntries) {
- const QLatin1String libraryName(qtModule.libraryName);
+ const QString &libraryName = qtModule.name;
if (module == libraryName
|| (module.size() == libraryName.size() + 1 && module.startsWith(libraryName))) {
- return qtModule.module;
+ return qtModule.id;
}
}
- return 0;
+ std::wcerr << "Warning: module " << qPrintable(module) << " could not be found\n";
+ return -1;
}
-QStringList findQtPlugins(quint64 *usedQtModules, quint64 disabledQtModules,
- unsigned disabledPlugins,
- const QString &qtPluginsDirName, const QString &libraryLocation,
- const QString &infix,
- DebugMatchMode debugMatchModeIn, Platform platform, QString *platformPlugin)
+// Return the path if a plugin is to be deployed
+static QString deployPlugin(const QString &plugin, const QDir &subDir, const bool dueToModule,
+ const DebugMatchMode &debugMatchMode, ModuleBitset *pluginNeededQtModules,
+ const ModuleBitset &disabledQtModules,
+ const PluginSelections &pluginSelections, const QString &libraryLocation,
+ const QString &infix, Platform platform,
+ bool deployInsightTrackerPlugin, bool deployOpenSslPlugin)
{
+ const QString subDirName = subDir.dirName();
+ // Filter out disabled plugins
+ if (optVerboseLevel && pluginSelections.disabledPluginTypes.contains(subDirName)) {
+ std::wcout << "Skipping plugin " << plugin << " due to skipped plugin type " << subDirName << '\n';
+ return {};
+ }
+ if (optVerboseLevel && subDirName == u"generic" && plugin.contains(u"qinsighttracker")
+ && !deployInsightTrackerPlugin) {
+ std::wcout << "Skipping plugin " << plugin
+ << ". Use -deploy-insighttracker if you want to use it.\n";
+ return {};
+ }
+ if (optVerboseLevel && subDirName == u"tls" && plugin.contains(u"qopensslbackend")
+ && !deployOpenSslPlugin) {
+ std::wcout << "Skipping plugin " << plugin
+ << ". Use -force_openssl or specify -openssl-root if you want to use it.\n";
+ return {};
+ }
+
+ const int dotIndex = plugin.lastIndexOf(u'.');
+ // Strip the .dll from the name, and an additional 'd' if it's a debug library with the 'd'
+ // suffix
+ const int stripIndex = debugMatchMode == MatchDebug && platformHasDebugSuffix(platform)
+ ? dotIndex - 1
+ : dotIndex;
+ const QString pluginName = plugin.first(stripIndex);
+
+ if (optVerboseLevel && pluginSelections.excludedPlugins.contains(pluginName)) {
+ std::wcout << "Skipping plugin " << plugin << " due to exclusion option" << '\n';
+ return {};
+ }
+
+ // By default, only deploy qwindows.dll
+ if (subDirName == u"platforms"
+ && !(pluginSelections.includedPlugins.contains(pluginName)
+ || (pluginSelections.enabledPluginTypes.contains(subDirName)))
+ && !pluginName.startsWith(u"qwindows")) {
+ return {};
+ }
+
+ const QString pluginPath = subDir.absoluteFilePath(plugin);
+
+ // If dueToModule is false, check if the user included the plugin or the entire type. In the
+ // former's case, only deploy said plugin and not all plugins of that type.
+ const bool requiresPlugin = pluginSelections.includedPlugins.contains(pluginName)
+ || pluginSelections.enabledPluginTypes.contains(subDirName);
+ if (!dueToModule && !requiresPlugin)
+ return {};
+
+ // Deploy QUiTools plugins as is without further dependency checking.
+ // The user needs to ensure all required libraries are present (would
+ // otherwise pull QtWebEngine for its plugin).
+ if (subDirName == u"designer")
+ return pluginPath;
+
+ QStringList dependentQtLibs;
QString errorMessage;
+ if (findDependentQtLibraries(libraryLocation, pluginPath, platform,
+ &errorMessage, &dependentQtLibs)) {
+ for (int d = 0; d < dependentQtLibs.size(); ++d) {
+ const qint64 module = qtModule(dependentQtLibs.at(d), infix);
+ if (module >= 0)
+ (*pluginNeededQtModules)[module] = 1;
+ }
+ } else {
+ std::wcerr << "Warning: Cannot determine dependencies of "
+ << QDir::toNativeSeparators(pluginPath) << ": " << errorMessage << '\n';
+ }
+
+ ModuleBitset disabledNeededQtModules;
+ disabledNeededQtModules = *pluginNeededQtModules & disabledQtModules;
+ if (disabledNeededQtModules.any()) {
+ if (optVerboseLevel) {
+ std::wcout << "Skipping plugin " << plugin
+ << " due to disabled dependencies ("
+ << formatQtModules(disabledNeededQtModules).constData() << ").\n";
+ }
+ return {};
+ }
+
+ return pluginPath;
+}
+
+static bool needsPluginType(const QString &subDirName, const PluginInformation &pluginInfo,
+ const PluginSelections &pluginSelections)
+{
+ bool needsTypeForPlugin = false;
+ for (const QString &plugin: pluginSelections.includedPlugins) {
+ if (pluginInfo.isTypeForPlugin(subDirName, plugin))
+ needsTypeForPlugin = true;
+ }
+ return (pluginSelections.enabledPluginTypes.contains(subDirName) || needsTypeForPlugin);
+}
+
+QStringList findQtPlugins(ModuleBitset *usedQtModules, const ModuleBitset &disabledQtModules,
+ const PluginInformation &pluginInfo, const PluginSelections &pluginSelections,
+ const QString &qtPluginsDirName, const QString &libraryLocation,
+ const QString &infix, DebugMatchMode debugMatchModeIn, Platform platform,
+ QString *platformPlugin, bool deployInsightTrackerPlugin,
+ bool deployOpenSslPlugin)
+{
if (qtPluginsDirName.isEmpty())
return QStringList();
QDir pluginsDir(qtPluginsDirName);
QStringList result;
- const QFileInfoList &pluginDirs = pluginsDir.entryInfoList(QStringList(QLatin1String("*")), QDir::Dirs | QDir::NoDotAndDotDot);
+ bool missingQtModulesAdded = false;
+ const QFileInfoList &pluginDirs = pluginsDir.entryInfoList(QStringList(u"*"_s), QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &subDirFi : pluginDirs) {
const QString subDirName = subDirFi.fileName();
- const quint64 module = qtModuleForPlugin(subDirName);
- if (module & *usedQtModules) {
- const DebugMatchMode debugMatchMode = (module & QtWebEngineCoreModule)
+ const size_t module = qtModuleEntries.moduleIdForPluginType(subDirName);
+ if (module == QtModule::InvalidId) {
+ if (optVerboseLevel > 1) {
+ std::wcerr << "No Qt module found for plugin type \"" << subDirName << "\".\n";
+ }
+ continue;
+ }
+ const bool dueToModule = usedQtModules->test(module);
+ if (dueToModule || needsPluginType(subDirName, pluginInfo, pluginSelections)) {
+ const DebugMatchMode debugMatchMode = (module == QtWebEngineCoreModuleId)
? MatchDebugOrRelease // QTBUG-44331: Debug detection does not work for webengine, deploy all.
: debugMatchModeIn;
QDir subDir(subDirFi.absoluteFilePath());
- // Filter out disabled plugins
- if ((disabledPlugins & QtVirtualKeyboardPlugin) && subDirName == QLatin1String("virtualkeyboard"))
- continue;
- if (disabledQtModules & QtQmlToolingModule && subDirName == QLatin1String("qmltooling"))
- continue;
- // Filter for platform or any.
- QString filter;
- const bool isPlatformPlugin = subDirName == QLatin1String("platforms");
- if (isPlatformPlugin) {
- switch (platform) {
- case WindowsDesktopMsvc:
- case WindowsDesktopMinGW:
- filter = QStringLiteral("qwindows");
- break;
- case Unix:
- filter = QStringLiteral("libqxcb");
- break;
- case UnknownPlatform:
- break;
- }
- } else {
- filter = QLatin1String("*");
- }
- const QStringList plugins = findSharedLibraries(subDir, platform, debugMatchMode, filter);
+ if (optVerboseLevel)
+ std::wcout << "Adding in plugin type " << subDirFi.baseName() << " for module: " << qtModuleEntries.moduleById(module).name << '\n';
+
+ const bool isPlatformPlugin = subDirName == "platforms"_L1;
+ const QStringList plugins =
+ findSharedLibraries(subDir, platform, debugMatchMode, QString());
for (const QString &plugin : plugins) {
- // Filter out disabled plugins
- if ((disabledPlugins & QtVirtualKeyboardPlugin)
- && plugin.startsWith(QLatin1String("qtvirtualkeyboardplugin"))) {
- continue;
- }
- const QString pluginPath = subDir.absoluteFilePath(plugin);
- if (isPlatformPlugin)
- *platformPlugin = pluginPath;
- QStringList dependentQtLibs;
- quint64 neededModules = 0;
- if (findDependentQtLibraries(libraryLocation, pluginPath, platform, &errorMessage, &dependentQtLibs)) {
- for (int d = 0; d < dependentQtLibs.size(); ++ d)
- neededModules |= qtModule(dependentQtLibs.at(d), infix);
- } else {
- std::wcerr << "Warning: Cannot determine dependencies of "
- << QDir::toNativeSeparators(pluginPath) << ": " << errorMessage << '\n';
- }
- if (const quint64 missingModules = neededModules & disabledQtModules) {
- if (optVerboseLevel) {
- std::wcout << "Skipping plugin " << plugin
- << " due to disabled dependencies ("
- << formatQtModules(missingModules).constData() << ").\n";
- }
- } else {
- if (const quint64 missingModules = (neededModules & ~*usedQtModules)) {
+ ModuleBitset pluginNeededQtModules;
+ const QString pluginPath =
+ deployPlugin(plugin, subDir, dueToModule, debugMatchMode, &pluginNeededQtModules,
+ disabledQtModules, pluginSelections, libraryLocation, infix,
+ platform, deployInsightTrackerPlugin, deployOpenSslPlugin);
+ if (!pluginPath.isEmpty()) {
+ if (isPlatformPlugin && plugin.startsWith(u"qwindows"))
+ *platformPlugin = subDir.absoluteFilePath(plugin);
+ result.append(pluginPath);
+
+ const ModuleBitset missingModules = (pluginNeededQtModules & ~*usedQtModules);
+ if (missingModules.any()) {
*usedQtModules |= missingModules;
- if (optVerboseLevel)
- std::wcout << "Adding " << formatQtModules(missingModules).constData() << " for " << plugin << '\n';
+ missingQtModulesAdded = true;
+ if (optVerboseLevel) {
+ std::wcout << "Adding " << formatQtModules(missingModules).constData()
+ << " for " << plugin << " from plugin type: " << subDirName << '\n';
+ }
}
- result.append(pluginPath);
}
} // for filter
} // type matches
} // for plugin folder
+
+ // If missing Qt modules were added during plugin deployment make additional pass, because we may need
+ // additional plugins.
+ if (pluginSelections.includeSoftPlugins && missingQtModulesAdded) {
+ if (optVerboseLevel) {
+ std::wcout << "Performing additional pass of finding Qt plugins due to updated Qt module list: "
+ << formatQtModules(*usedQtModules).constData() << "\n";
+ }
+ return findQtPlugins(usedQtModules, disabledQtModules, pluginInfo, pluginSelections, qtPluginsDirName,
+ libraryLocation, infix, debugMatchModeIn, platform, platformPlugin,
+ deployInsightTrackerPlugin, deployOpenSslPlugin);
+ }
+
return result;
}
-static QStringList translationNameFilters(quint64 modules, const QString &prefix)
+static QStringList translationNameFilters(const ModuleBitset &modules, const QString &prefix)
{
QStringList result;
for (const auto &qtModule : qtModuleEntries) {
- if ((qtModule.module & modules) && qtModule.translation) {
- const QString name = QLatin1String(qtModule.translation) +
- QLatin1Char('_') + prefix + QStringLiteral(".qm");
+ if (modules.test(qtModule.id) && !qtModule.translationCatalog.isEmpty()) {
+ const QString name = qtModule.translationCatalog + u'_' + prefix + ".qm"_L1;
if (!result.contains(name))
result.push_back(name);
}
@@ -998,7 +1147,7 @@ static QStringList translationNameFilters(quint64 modules, const QString &prefix
return result;
}
-static bool deployTranslations(const QString &sourcePath, quint64 usedQtModules,
+static bool deployTranslations(const QString &sourcePath, const ModuleBitset &usedQtModules,
const QString &target, const Options &options,
QString *errorMessage)
{
@@ -1022,15 +1171,20 @@ static bool deployTranslations(const QString &sourcePath, quint64 usedQtModules,
const QString absoluteTarget = QFileInfo(target).absoluteFilePath();
const QString binary = QStringLiteral("lconvert");
QStringList arguments;
- for (const QString &prefix : qAsConst(prefixes)) {
+ for (const QString &prefix : std::as_const(prefixes)) {
arguments.clear();
const QString targetFile = QStringLiteral("qt_") + prefix + QStringLiteral(".qm");
arguments.append(QStringLiteral("-o"));
- const QString targetFilePath = absoluteTarget + QLatin1Char('/') + targetFile;
+ const QString targetFilePath = absoluteTarget + u'/' + targetFile;
if (options.json)
- options.json->addFile(sourcePath + QLatin1Char('/') + targetFile, absoluteTarget);
+ options.json->addFile(sourcePath + u'/' + targetFile, absoluteTarget);
arguments.append(QDir::toNativeSeparators(targetFilePath));
- const QFileInfoList &langQmFiles = sourceDir.entryInfoList(translationNameFilters(usedQtModules, prefix));
+ const QStringList translationFilters = translationNameFilters(usedQtModules, prefix);
+ if (translationFilters.isEmpty()){
+ std::wcerr << "Warning: translation catalogs are all empty, skipping translation deployment\n";
+ return true;
+ }
+ const QFileInfoList &langQmFiles = sourceDir.entryInfoList(translationFilters);
for (const QFileInfo &langQmFileFi : langQmFiles) {
if (options.json) {
options.json->addFile(langQmFileFi.absoluteFilePath(),
@@ -1050,32 +1204,82 @@ static bool deployTranslations(const QString &sourcePath, quint64 usedQtModules,
return true;
}
+static QStringList findFFmpegLibs(const QString &qtBinDir, Platform platform)
+{
+ const std::vector<QLatin1StringView> ffmpegHints = { "avcodec"_L1, "avformat"_L1, "avutil"_L1,
+ "swresample"_L1, "swscale"_L1 };
+ const QStringList bundledLibs =
+ findSharedLibraries(qtBinDir, platform, MatchDebugOrRelease, {});
+
+ QStringList ffmpegLibs;
+ for (const QLatin1StringView &libHint : ffmpegHints) {
+ const QStringList ffmpegLib = bundledLibs.filter(libHint, Qt::CaseInsensitive);
+
+ if (ffmpegLib.empty()) {
+ std::wcerr << "Warning: Cannot find FFmpeg libraries. Multimedia features will not work as expected.\n";
+ return {};
+ } else if (ffmpegLib.size() != 1u) {
+ std::wcerr << "Warning: Multiple versions of FFmpeg libraries found. Multimedia features will not work as expected.\n";
+ return {};
+ }
+
+ const QChar slash(u'/');
+ QFileInfo ffmpegLibPath{ qtBinDir + slash + ffmpegLib.front() };
+ ffmpegLibs.append(ffmpegLibPath.absoluteFilePath());
+ }
+
+ return ffmpegLibs;
+}
+
+// Find the openssl libraries Qt executables depend on.
+static QStringList findOpenSslLibraries(const QString &openSslRootDir, Platform platform)
+{
+ const std::vector<QLatin1StringView> libHints = { "libcrypto"_L1, "libssl"_L1 };
+ const QChar slash(u'/');
+ const QString openSslBinDir = openSslRootDir + slash + "bin"_L1;
+ const QStringList openSslRootLibs =
+ findSharedLibraries(openSslBinDir, platform, MatchDebugOrRelease, {});
+
+ QStringList result;
+ for (const QLatin1StringView &libHint : libHints) {
+ const QStringList lib = openSslRootLibs.filter(libHint, Qt::CaseInsensitive);
+
+ if (lib.empty()) {
+ std::wcerr << "Warning: Cannot find openssl libraries.\n";
+ return {};
+ } else if (lib.size() != 1u) {
+ std::wcerr << "Warning: Multiple versions of openssl libraries found.\n";
+ return {};
+ }
+
+ QFileInfo libPath{ openSslBinDir + slash + lib.front() };
+ result.append(libPath.absoluteFilePath());
+ }
+
+ return result;
+}
+
+
struct DeployResult
{
operator bool() const { return success; }
bool success = false;
bool isDebug = false;
- quint64 directlyUsedQtLibraries = 0;
- quint64 usedQtLibraries = 0;
- quint64 deployedQtLibraries = 0;
+ ModuleBitset directlyUsedQtLibraries;
+ ModuleBitset usedQtLibraries;
+ ModuleBitset deployedQtLibraries;
};
static QString libraryPath(const QString &libraryLocation, const char *name,
- const QString &qtLibInfix, Platform platform, bool debug)
+ const QString &infix, Platform platform, bool debug)
{
- QString result = libraryLocation + QLatin1Char('/');
- if (platform & WindowsBased) {
- result += QLatin1String(name);
- result += qtLibInfix;
- if (debug && platformHasDebugSuffix(platform))
- result += QLatin1Char('d');
- } else if (platform.testFlag(UnixBased)) {
- result += QStringLiteral("lib");
- result += QLatin1String(name);
- result += qtLibInfix;
- }
- result += sharedLibrarySuffix(platform);
+ QString result = libraryLocation + u'/';
+ result += QLatin1StringView(name);
+ result += infix;
+ if (debug && platformHasDebugSuffix(platform))
+ result += u'd';
+ result += sharedLibrarySuffix();
return result;
}
@@ -1084,7 +1288,7 @@ static QString vcDebugRedistDir() { return QStringLiteral("Debug_NonRedist"); }
static QString vcRedistDir()
{
const char vcDirVar[] = "VCINSTALLDIR";
- const QChar slash(QLatin1Char('/'));
+ const QChar slash(u'/');
QString vcRedistDirName = QDir::cleanPath(QFile::decodeName(qgetenv(vcDirVar)));
if (vcRedistDirName.isEmpty()) {
std::wcerr << "Warning: Cannot find Visual Studio installation directory, " << vcDirVar
@@ -1116,27 +1320,48 @@ static QString vcRedistDir()
return QString();
}
-static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned short machineArch)
+static QStringList findMinGWRuntimePaths(const QString &qtBinDir, Platform platform, const QStringList &runtimeFilters)
{
+ //MinGW: Add runtime libraries. Check first for the Qt binary directory, and default to path if nothing is found.
QStringList result;
- switch (platform) {
- case WindowsDesktopMinGW: { // MinGW: Add runtime libraries
- static const char *minGwRuntimes[] = {"*gcc_", "*stdc++", "*winpthread"};
- const QString gcc = findInPath(QStringLiteral("g++.exe"));
- if (gcc.isEmpty()) {
- std::wcerr << "Warning: Cannot find GCC installation directory. g++.exe must be in the path.\n";
- break;
+ const bool isClang = platform == WindowsDesktopClangMinGW;
+ QStringList filters;
+ const QString suffix = u'*' + sharedLibrarySuffix();
+ for (const auto &minGWRuntime : runtimeFilters)
+ filters.append(minGWRuntime + suffix);
+
+ QFileInfoList dlls = QDir(qtBinDir).entryInfoList(filters, QDir::Files);
+ if (dlls.isEmpty()) {
+ std::wcerr << "Warning: Runtime libraries not found in Qt binary folder, defaulting to looking in path\n";
+ const QString binaryPath = isClang ? findInPath("clang++.exe"_L1) : findInPath("g++.exe"_L1);
+ if (binaryPath.isEmpty()) {
+ std::wcerr << "Warning: Cannot find " << (isClang ? "Clang" : "GCC") << " installation directory, " << (isClang ? "clang++" : "g++") << ".exe must be in the path\n";
+ return {};
}
- const QString binPath = QFileInfo(gcc).absolutePath();
- QStringList filters;
- const QString suffix = QLatin1Char('*') + sharedLibrarySuffix(platform);
- for (auto minGwRuntime : minGwRuntimes)
- filters.append(QLatin1String(minGwRuntime) + suffix);
- const QFileInfoList &dlls = QDir(binPath).entryInfoList(filters, QDir::Files);
- for (const QFileInfo &dllFi : dlls)
- result.append(dllFi.absoluteFilePath());
+ const QString binaryFolder = QFileInfo(binaryPath).absolutePath();
+ dlls = QDir(binaryFolder).entryInfoList(filters, QDir::Files);
+ }
+
+ for (const QFileInfo &dllFi : dlls)
+ result.append(dllFi.absoluteFilePath());
+
+ return result;
+}
+
+static QStringList compilerRunTimeLibs(const QString &qtBinDir, Platform platform, bool isDebug, unsigned short machineArch)
+{
+ QStringList result;
+ switch (platform) {
+ case WindowsDesktopMinGW: {
+ const QStringList minGWRuntimes = { "*gcc_"_L1, "*stdc++"_L1, "*winpthread"_L1 };
+ result.append(findMinGWRuntimePaths(qtBinDir, platform, minGWRuntimes));
+ break;
}
+ case WindowsDesktopClangMinGW: {
+ const QStringList clangMinGWRuntimes = { "*unwind"_L1, "*c++"_L1 };
+ result.append(findMinGWRuntimePaths(qtBinDir, platform, clangMinGWRuntimes));
break;
+ }
#ifdef Q_OS_WIN
case WindowsDesktopMsvc: { // MSVC/Desktop: Add redistributable packages.
QString vcRedistDirName = vcRedistDir();
@@ -1150,7 +1375,7 @@ static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned
if (vcRedistDir.cd(vcDebugRedistDir()) && vcRedistDir.cd(machineArchString)) {
const QStringList names = vcRedistDir.entryList(QStringList(QStringLiteral("Microsoft.VC*.DebugCRT")), QDir::Dirs);
if (!names.isEmpty() && vcRedistDir.cd(names.first())) {
- const QFileInfoList &dlls = vcRedistDir.entryInfoList(QStringList(QLatin1String("*.dll")));
+ const QFileInfoList &dlls = vcRedistDir.entryInfoList(QStringList("*.dll"_L1));
for (const QFileInfo &dll : dlls)
redistFiles.append(dll.absoluteFilePath());
}
@@ -1159,12 +1384,12 @@ static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned
QString releaseRedistDir = vcRedistDirName;
const QStringList countryCodes = vcRedistDir.entryList(QStringList(QStringLiteral("[0-9]*")), QDir::Dirs);
if (!countryCodes.isEmpty()) // Pre MSVC2017
- releaseRedistDir += QLatin1Char('/') + countryCodes.constFirst();
- QFileInfo fi(releaseRedistDir + QLatin1Char('/') + QStringLiteral("vc_redist.")
- + machineArchString + QStringLiteral(".exe"));
+ releaseRedistDir += u'/' + countryCodes.constFirst();
+ QFileInfo fi(releaseRedistDir + "/vc_redist."_L1
+ + machineArchString + ".exe"_L1);
if (!fi.isFile()) { // Pre MSVC2017/15.5
- fi.setFile(releaseRedistDir + QLatin1Char('/') + QStringLiteral("vcredist_")
- + machineArchString + QStringLiteral(".exe"));
+ fi.setFile(releaseRedistDir + "/vcredist_"_L1
+ + machineArchString + ".exe"_L1);
}
if (fi.isFile())
redistFiles.append(fi.absoluteFilePath());
@@ -1187,23 +1412,13 @@ static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned
static inline int qtVersion(const QMap<QString, QString> &qtpathsVariables)
{
const QString versionString = qtpathsVariables.value(QStringLiteral("QT_VERSION"));
- const QChar dot = QLatin1Char('.');
+ const QChar dot = u'.';
const int majorVersion = versionString.section(dot, 0, 0).toInt();
const int minorVersion = versionString.section(dot, 1, 1).toInt();
const int patchVersion = versionString.section(dot, 2, 2).toInt();
return (majorVersion << 16) | (minorVersion << 8) | patchVersion;
}
-// Determine the Qt lib infix from the library path of "Qt6Core<qtblibinfix>[d].dll".
-static inline QString qtlibInfixFromCoreLibName(const QString &path, bool isDebug, Platform platform)
-{
- const int startPos = path.lastIndexOf(QLatin1Char('/')) + 8;
- int endPos = path.lastIndexOf(QLatin1Char('.'));
- if (isDebug && (platform & WindowsBased))
- endPos--;
- return endPos > startPos ? path.mid(startPos, endPos - startPos) : QString();
-}
-
// Deploy a library along with its .pdb debug info file (MSVC) should it exist.
static bool updateLibrary(const QString &sourceFileName, const QString &targetDirectory,
const Options &options, QString *errorMessage)
@@ -1236,17 +1451,15 @@ static QString getIcuVersion(const QString &libName)
}
static DeployResult deploy(const Options &options, const QMap<QString, QString> &qtpathsVariables,
- QString *errorMessage)
+ const PluginInformation &pluginInfo, QString *errorMessage)
{
DeployResult result;
- const QChar slash = QLatin1Char('/');
+ const QChar slash = u'/';
const QString qtBinDir = qtpathsVariables.value(QStringLiteral("QT_INSTALL_BINS"));
- const QString libraryLocation = options.platform == Unix
- ? qtpathsVariables.value(QStringLiteral("QT_INSTALL_LIBS"))
- : qtBinDir;
- const QString infix = qtpathsVariables.value(QLatin1String(qmakeInfixKey));
+ const QString libraryLocation = qtBinDir;
+ const QString infix = qtpathsVariables.value(QLatin1StringView(qmakeInfixKey));
const int version = qtVersion(qtpathsVariables);
Q_UNUSED(version);
@@ -1292,17 +1505,17 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
// Determine application type, check Quick2 is used by looking at the
// direct dependencies (do not be fooled by QtWebKit depending on it).
- QString qtLibInfix;
- for (int m = 0; m < directDependencyCount; ++m) {
- const quint64 module = qtModule(dependentQtLibs.at(m), infix);
- result.directlyUsedQtLibraries |= module;
- if (module == QtCoreModule)
- qtLibInfix = qtlibInfixFromCoreLibName(dependentQtLibs.at(m), detectedDebug, options.platform);
+ for (int m = 0; m < dependentQtLibs.size(); ++m) {
+ const qint64 module = qtModule(dependentQtLibs.at(m), infix);
+ if (module >= 0)
+ result.directlyUsedQtLibraries[module] = 1;
}
- const bool usesQml2 = !(options.disabledLibraries & QtQmlModule)
- && ((result.directlyUsedQtLibraries & (QtQmlModule | QtQuickModule | Qt3DQuickModule))
- || (options.additionalLibraries & QtQmlModule));
+ const bool usesQml = result.directlyUsedQtLibraries.test(QtQmlModuleId);
+ const bool usesQuick = result.directlyUsedQtLibraries.test(QtQuickModuleId);
+ const bool uses3DQuick = result.directlyUsedQtLibraries.test(Qt3DQuickModuleId);
+ const bool usesQml2 = !(options.disabledLibraries.test(QtQmlModuleId))
+ && (usesQml || usesQuick || uses3DQuick || (options.additionalLibraries.test(QtQmlModuleId)));
if (optVerboseLevel) {
std::wcout << QDir::toNativeSeparators(options.binaries.first()) << ' '
@@ -1324,7 +1537,7 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
const QStringList qtLibs = dependentQtLibs.filter(QStringLiteral("Qt6Core"), Qt::CaseInsensitive)
+ dependentQtLibs.filter(QStringLiteral("Qt5WebKit"), Qt::CaseInsensitive);
for (const QString &qtLib : qtLibs) {
- QStringList icuLibs = findDependentLibraries(qtLib, options.platform, errorMessage).filter(QStringLiteral("ICU"), Qt::CaseInsensitive);
+ QStringList icuLibs = findDependentLibraries(qtLib, errorMessage).filter(QStringLiteral("ICU"), Qt::CaseInsensitive);
if (!icuLibs.isEmpty()) {
// Find out the ICU version to add the data library icudtXX.dll, which does not show
// as a dependency.
@@ -1333,19 +1546,19 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
if (optVerboseLevel > 1)
std::wcout << "Adding ICU version " << icuVersion << '\n';
QString icuLib = QStringLiteral("icudt") + icuVersion
- + QLatin1String(windowsSharedLibrarySuffix);;
+ + QLatin1StringView(windowsSharedLibrarySuffix);
// Some packages contain debug dlls of ICU libraries even though it's a C
// library and the official packages do not differentiate (QTBUG-87677)
if (result.isDebug) {
const QString icuLibCandidate = QStringLiteral("icudtd") + icuVersion
- + QLatin1String(windowsSharedLibrarySuffix);
+ + QLatin1StringView(windowsSharedLibrarySuffix);
if (!findInPath(icuLibCandidate).isEmpty()) {
icuLib = icuLibCandidate;
}
}
icuLibs.push_back(icuLib);
}
- for (const QString &icuLib : qAsConst(icuLibs)) {
+ for (const QString &icuLib : std::as_const(icuLibs)) {
const QString icuPath = findInPath(icuLib);
if (icuPath.isEmpty()) {
*errorMessage = QStringLiteral("Unable to locate ICU library ") + icuLib;
@@ -1371,30 +1584,30 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
if (!qmlDirectory.isEmpty())
qmlDirectories.append(qmlDirectory);
}
- for (const QString &qmlDirectory : qAsConst(qmlDirectories)) {
+ for (const QString &qmlDirectory : std::as_const(qmlDirectories)) {
if (optVerboseLevel >= 1)
std::wcout << "Scanning " << QDir::toNativeSeparators(qmlDirectory) << ":\n";
const QmlImportScanResult scanResult =
runQmlImportScanner(qmlDirectory, qmlImportPaths,
- result.directlyUsedQtLibraries & QtWidgetsModule,
+ result.directlyUsedQtLibraries.test(QtWidgetsModuleId),
options.platform, debugMatchMode, errorMessage);
if (!scanResult.ok)
return result;
qmlScanResult.append(scanResult);
// Additional dependencies of QML plugins.
- for (const QString &plugin : qAsConst(qmlScanResult.plugins)) {
+ for (const QString &plugin : std::as_const(qmlScanResult.plugins)) {
if (!findDependentQtLibraries(libraryLocation, plugin, options.platform, errorMessage, &dependentQtLibs, &wordSize, &detectedDebug, &machineArch))
return result;
}
if (optVerboseLevel >= 1) {
std::wcout << "QML imports:\n";
- for (const QmlImportScanResult::Module &mod : qAsConst(qmlScanResult.modules)) {
+ for (const QmlImportScanResult::Module &mod : std::as_const(qmlScanResult.modules)) {
std::wcout << " '" << mod.name << "' "
<< QDir::toNativeSeparators(mod.sourcePath) << '\n';
}
if (optVerboseLevel >= 2) {
std::wcout << "QML plugins:\n";
- for (const QString &p : qAsConst(qmlScanResult.plugins))
+ for (const QString &p : std::as_const(qmlScanResult.plugins))
std::wcout << " " << QDir::toNativeSeparators(p) << '\n';
}
}
@@ -1406,28 +1619,50 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
// QtModule enumeration (and thus controlled by flags) and others.
QStringList deployedQtLibraries;
for (int i = 0 ; i < dependentQtLibs.size(); ++i) {
- if (const quint64 qtm = qtModule(dependentQtLibs.at(i), infix))
- result.usedQtLibraries |= qtm;
+ const qint64 module = qtModule(dependentQtLibs.at(i), infix);
+ if (module >= 0)
+ result.usedQtLibraries[module] = 1;
else
deployedQtLibraries.push_back(dependentQtLibs.at(i)); // Not represented by flag.
}
result.deployedQtLibraries = (result.usedQtLibraries | options.additionalLibraries) & ~options.disabledLibraries;
+ ModuleBitset disabled = options.disabledLibraries;
+ if (!usesQml2) {
+ disabled[QtQmlModuleId] = 1;
+ disabled[QtQuickModuleId] = 1;
+ }
+
+ QStringList openSslLibs;
+ if (!options.openSslRootDirectory.isEmpty()) {
+ openSslLibs = findOpenSslLibraries(options.openSslRootDirectory, options.platform);
+ if (openSslLibs.isEmpty()) {
+ *errorMessage = QStringLiteral("Unable to find openSSL libraries in ")
+ + options.openSslRootDirectory;
+ return result;
+ }
+
+ deployedQtLibraries.append(openSslLibs);
+ }
+ const bool deployOpenSslPlugin = options.forceOpenSslPlugin || !openSslLibs.isEmpty();
+
const QStringList plugins = findQtPlugins(
&result.deployedQtLibraries,
// For non-QML applications, disable QML to prevent it from being pulled in by the
// qtaccessiblequick plugin.
- options.disabledLibraries | (usesQml2 ? 0 : (QtQmlModule | QtQuickModule)),
- options.disabledPlugins, qtpathsVariables.value(QStringLiteral("QT_INSTALL_PLUGINS")),
- libraryLocation, infix, debugMatchMode, options.platform, &platformPlugin);
+ disabled, pluginInfo,
+ options.pluginSelections, qtpathsVariables.value(QStringLiteral("QT_INSTALL_PLUGINS")),
+ libraryLocation, infix, debugMatchMode, options.platform, &platformPlugin,
+ options.deployInsightTrackerPlugin, deployOpenSslPlugin);
// Apply options flags and re-add library names.
QString qtGuiLibrary;
for (const auto &qtModule : qtModuleEntries) {
- if (result.deployedQtLibraries & qtModule.module) {
- const QString library = libraryPath(libraryLocation, qtModule.libraryName, qtLibInfix, options.platform, result.isDebug);
+ if (result.deployedQtLibraries.test(qtModule.id)) {
+ const QString library = libraryPath(libraryLocation, qtModule.name.toUtf8(), infix,
+ options.platform, result.isDebug);
deployedQtLibraries.append(library);
- if (qtModule.module == QtGuiModule)
+ if (qtModule.id == QtGuiModuleId)
qtGuiLibrary = library;
}
}
@@ -1439,18 +1674,18 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
}
if (optVerboseLevel > 1)
- std::wcout << "Plugins: " << plugins.join(QLatin1Char(',')) << '\n';
+ std::wcout << "Plugins: " << plugins.join(u',') << '\n';
- if ((result.deployedQtLibraries & QtGuiModule) && platformPlugin.isEmpty()) {
+ if (result.deployedQtLibraries.test(QtGuiModuleId) && platformPlugin.isEmpty()) {
*errorMessage =QStringLiteral("Unable to find the platform plugin.");
return result;
}
if (options.platform.testFlag(WindowsBased) && !qtGuiLibrary.isEmpty()) {
- const QStringList guiLibraries = findDependentLibraries(qtGuiLibrary, options.platform, errorMessage);
+ const QStringList guiLibraries = findDependentLibraries(qtGuiLibrary, errorMessage);
const bool dependsOnOpenGl = !guiLibraries.filter(QStringLiteral("opengl32"), Qt::CaseInsensitive).isEmpty();
if (options.softwareRasterizer && !dependsOnOpenGl) {
- const QFileInfo softwareRasterizer(qtBinDir + slash + QStringLiteral("opengl32sw") + QLatin1String(windowsSharedLibrarySuffix));
+ const QFileInfo softwareRasterizer(qtBinDir + slash + QStringLiteral("opengl32sw") + QLatin1StringView(windowsSharedLibrarySuffix));
if (softwareRasterizer.isFile())
deployedQtLibraries.append(softwareRasterizer.absoluteFilePath());
}
@@ -1462,30 +1697,43 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
deployedQtLibraries.push_back(d3dCompiler);
}
}
+ if (options.systemDxc) {
+ const QStringList dxcLibs = findDxc(options.platform, qtBinDir, wordSize);
+ if (!dxcLibs.isEmpty())
+ deployedQtLibraries.append(dxcLibs);
+ else
+ std::wcerr << "Warning: Cannot find any version of the dxcompiler.dll and dxil.dll.\n";
+ }
} // Windows
+ // Add FFmpeg if we deploy the FFmpeg backend
+ if (options.ffmpeg
+ && !plugins.filter(QStringLiteral("ffmpegmediaplugin"), Qt::CaseInsensitive).empty()) {
+ deployedQtLibraries.append(findFFmpegLibs(qtBinDir, options.platform));
+ }
+
// Update libraries
if (options.libraries) {
const QString targetPath = options.libraryDirectory.isEmpty() ?
options.directory : options.libraryDirectory;
QStringList libraries = deployedQtLibraries;
if (options.compilerRunTime)
- libraries.append(compilerRunTimeLibs(options.platform, result.isDebug, machineArch));
- for (const QString &qtLib : qAsConst(libraries)) {
+ libraries.append(compilerRunTimeLibs(qtBinDir, options.platform, result.isDebug, machineArch));
+ for (const QString &qtLib : std::as_const(libraries)) {
if (!updateLibrary(qtLib, targetPath, options, errorMessage))
return result;
}
+#if !QT_CONFIG(relocatable)
if (options.patchQt && !options.dryRun) {
- const QString qt6CoreName = QFileInfo(libraryPath(libraryLocation, "Qt6Core", qtLibInfix,
+ const QString qt6CoreName = QFileInfo(libraryPath(libraryLocation, "Qt6Core", infix,
options.platform, result.isDebug)).fileName();
-#ifndef QT_RELOCATABLE
- if (!patchQtCore(targetPath + QLatin1Char('/') + qt6CoreName, errorMessage)) {
+ if (!patchQtCore(targetPath + u'/' + qt6CoreName, errorMessage)) {
std::wcerr << "Warning: " << *errorMessage << '\n';
errorMessage->clear();
}
-#endif
}
+#endif // QT_CONFIG(relocatable)
} // optLibraries
// Update plugins
@@ -1494,8 +1742,8 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
options.directory : options.pluginDirectory;
QDir dir(targetPath);
if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) {
- *errorMessage = QLatin1String("Cannot create ") +
- QDir::toNativeSeparators(dir.absolutePath()) + QLatin1Char('.');
+ *errorMessage = "Cannot create "_L1 +
+ QDir::toNativeSeparators(dir.absolutePath()) + u'.';
return result;
}
for (const QString &plugin : plugins) {
@@ -1505,7 +1753,7 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
if (optVerboseLevel)
std::wcout << "Creating directory " << targetPath << ".\n";
if (!(options.updateFileFlags & SkipUpdateFile) && !dir.mkdir(targetDirName)) {
- *errorMessage = QStringLiteral("Cannot create ") + targetDirName + QLatin1Char('.');
+ *errorMessage = QStringLiteral("Cannot create ") + targetDirName + u'.';
return result;
}
}
@@ -1515,44 +1763,39 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
} // optPlugins
// Update Quick imports
- const bool usesQuick1 = result.deployedQtLibraries & QtDeclarativeModule;
// Do not be fooled by QtWebKit.dll depending on Quick into always installing Quick imports
// for WebKit1-applications. Check direct dependency only.
- if (options.quickImports && (usesQuick1 || usesQml2)) {
- if (usesQml2) {
- for (const QmlImportScanResult::Module &module : qAsConst(qmlScanResult.modules)) {
- const QString installPath = module.installPath(options.directory);
- if (optVerboseLevel > 1)
- std::wcout << "Installing: '" << module.name
- << "' from " << module.sourcePath << " to "
- << QDir::toNativeSeparators(installPath) << '\n';
- if (installPath != options.directory && !createDirectory(installPath, errorMessage))
- return result;
- unsigned updateFileFlags = options.updateFileFlags | SkipQmlDesignerSpecificsDirectories;
- unsigned qmlDirectoryFileFlags = 0;
- if (options.deployPdb)
- qmlDirectoryFileFlags |= QmlDirectoryFileEntryFunction::DeployPdb;
- if (!updateFile(module.sourcePath, QmlDirectoryFileEntryFunction(options.platform, debugMatchMode, qmlDirectoryFileFlags),
- installPath, updateFileFlags, options.json, errorMessage)) {
- return result;
- }
- }
- } // Quick 2
- if (usesQuick1) {
- const QString quick1ImportPath =
- qtpathsVariables.value(QStringLiteral("QT_INSTALL_IMPORTS"));
- const QmlDirectoryFileEntryFunction qmlFileEntryFunction(options.platform, debugMatchMode, options.deployPdb ? QmlDirectoryFileEntryFunction::DeployPdb : 0);
- QStringList quick1Imports(QStringLiteral("Qt"));
- for (const QString &quick1Import : qAsConst(quick1Imports)) {
- const QString sourceFile = quick1ImportPath + slash + quick1Import;
- if (!updateFile(sourceFile, qmlFileEntryFunction, options.directory, options.updateFileFlags, options.json, errorMessage))
- return result;
+ if (options.quickImports && usesQml2) {
+ const QString targetPath = options.qmlDirectory.isEmpty()
+ ? options.directory + QStringLiteral("/qml")
+ : options.qmlDirectory;
+ if (!createDirectory(targetPath, errorMessage, options.dryRun))
+ return result;
+ for (const QmlImportScanResult::Module &module : std::as_const(qmlScanResult.modules)) {
+ const QString installPath = module.installPath(targetPath);
+ if (optVerboseLevel > 1)
+ std::wcout << "Installing: '" << module.name
+ << "' from " << module.sourcePath << " to "
+ << QDir::toNativeSeparators(installPath) << '\n';
+ if (installPath != targetPath && !createDirectory(installPath, errorMessage, options.dryRun))
+ return result;
+ unsigned updateFileFlags = options.updateFileFlags
+ | SkipQmlDesignerSpecificsDirectories;
+ unsigned qmlDirectoryFileFlags = 0;
+ if (options.deployPdb)
+ qmlDirectoryFileFlags |= QmlDirectoryFileEntryFunction::DeployPdb;
+ if (!updateFile(module.sourcePath, QmlDirectoryFileEntryFunction(module.sourcePath,
+ options.platform,
+ debugMatchMode,
+ qmlDirectoryFileFlags),
+ installPath, updateFileFlags, options.json, errorMessage)) {
+ return result;
}
- } // Quick 1
+ }
} // optQuickImports
if (options.translations) {
- if (!options.dryRun && !createDirectory(options.translationsDirectory, errorMessage))
+ if (!createDirectory(options.translationsDirectory, errorMessage, options.dryRun))
return result;
if (!deployTranslations(qtpathsVariables.value(QStringLiteral("QT_INSTALL_TRANSLATIONS")),
result.deployedQtLibraries, options.translationsDirectory, options,
@@ -1566,44 +1809,48 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
}
static bool deployWebProcess(const QMap<QString, QString> &qtpathsVariables, const char *binaryName,
- const Options &sourceOptions, QString *errorMessage)
+ const PluginInformation &pluginInfo, const Options &sourceOptions,
+ QString *errorMessage)
{
// Copy the web process and its dependencies
const QString webProcess = webProcessBinary(binaryName, sourceOptions.platform);
const QString webProcessSource = qtpathsVariables.value(QStringLiteral("QT_INSTALL_LIBEXECS"))
- + QLatin1Char('/') + webProcess;
+ + u'/' + webProcess;
if (!updateFile(webProcessSource, sourceOptions.directory, sourceOptions.updateFileFlags, sourceOptions.json, errorMessage))
return false;
Options options(sourceOptions);
- options.binaries.append(options.directory + QLatin1Char('/') + webProcess);
+ options.binaries.append(options.directory + u'/' + webProcess);
options.quickImports = false;
options.translations = false;
- return deploy(options, qtpathsVariables, errorMessage);
+ return deploy(options, qtpathsVariables, pluginInfo, errorMessage);
}
static bool deployWebEngineCore(const QMap<QString, QString> &qtpathsVariables,
- const Options &options, bool isDebug, QString *errorMessage)
+ const PluginInformation &pluginInfo, const Options &options,
+ bool isDebug, QString *errorMessage)
{
- static const char *installDataFiles[] = {"icudtl.dat",
- "qtwebengine_devtools_resources.pak",
- "qtwebengine_resources.pak",
- "qtwebengine_resources_100p.pak",
- "qtwebengine_resources_200p.pak"};
+ static const char *installDataFiles[] = { "icudtl.dat",
+ "qtwebengine_devtools_resources.pak",
+ "qtwebengine_resources.pak",
+ "qtwebengine_resources_100p.pak",
+ "qtwebengine_resources_200p.pak",
+ isDebug ? "v8_context_snapshot.debug.bin"
+ : "v8_context_snapshot.bin" };
QByteArray webEngineProcessName(webEngineProcessC);
if (isDebug && platformHasDebugSuffix(options.platform))
webEngineProcessName.append('d');
if (optVerboseLevel)
std::wcout << "Deploying: " << webEngineProcessName.constData() << "...\n";
- if (!deployWebProcess(qtpathsVariables, webEngineProcessName, options, errorMessage))
+ if (!deployWebProcess(qtpathsVariables, webEngineProcessName, pluginInfo, options, errorMessage))
return false;
const QString resourcesSubDir = QStringLiteral("/resources");
const QString resourcesSourceDir = qtpathsVariables.value(QStringLiteral("QT_INSTALL_DATA"))
- + resourcesSubDir + QLatin1Char('/');
+ + resourcesSubDir + u'/';
const QString resourcesTargetDir(options.directory + resourcesSubDir);
- if (!createDirectory(resourcesTargetDir, errorMessage))
+ if (!createDirectory(resourcesTargetDir, errorMessage, options.dryRun))
return false;
for (auto installDataFile : installDataFiles) {
- if (!updateFile(resourcesSourceDir + QLatin1String(installDataFile),
+ if (!updateFile(resourcesSourceDir + QLatin1StringView(installDataFile),
resourcesTargetDir, options.updateFileFlags, options.json, errorMessage)) {
return false;
}
@@ -1617,7 +1864,7 @@ static bool deployWebEngineCore(const QMap<QString, QString> &qtpathsVariables,
}
if (options.translations) {
// Copy the whole translations directory.
- return createDirectory(options.translationsDirectory, errorMessage)
+ return createDirectory(options.translationsDirectory, errorMessage, options.dryRun)
&& updateFile(translations.absoluteFilePath(), options.translationsDirectory,
options.updateFileFlags, options.json, errorMessage);
}
@@ -1628,9 +1875,9 @@ static bool deployWebEngineCore(const QMap<QString, QString> &qtpathsVariables,
<< QDir::toNativeSeparators(enUSpak.absoluteFilePath()) << ".\n";
return true;
}
- const QString webEngineTranslationsDir = options.translationsDirectory + QLatin1Char('/')
+ const QString webEngineTranslationsDir = options.translationsDirectory + u'/'
+ translations.fileName();
- if (!createDirectory(webEngineTranslationsDir, errorMessage))
+ if (!createDirectory(webEngineTranslationsDir, errorMessage, options.dryRun))
return false;
return updateFile(enUSpak.absoluteFilePath(), webEngineTranslationsDir,
options.updateFileFlags, options.json, errorMessage);
@@ -1643,68 +1890,100 @@ QT_USE_NAMESPACE
int main(int argc, char **argv)
{
QCoreApplication a(argc, argv);
- QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
+ QCoreApplication::setApplicationVersion(QT_VERSION_STR ""_L1);
const QByteArray qtBinPath = QFile::encodeName(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()));
QByteArray path = qgetenv("PATH");
if (!path.contains(qtBinPath)) { // QTBUG-39177, ensure Qt is in the path so that qt.conf is taken into account.
- path += ';';
- path += qtBinPath;
+ path.prepend(QDir::listSeparator().toLatin1());
+ path.prepend(qtBinPath);
qputenv("PATH", path);
}
Options options;
QString errorMessage;
- { // Command line
- QCommandLineParser parser;
- QString errorMessage;
- const int result = parseArguments(QCoreApplication::arguments(), &parser, &options, &errorMessage);
- if (result & CommandLineParseError)
- std::wcerr << errorMessage << "\n\n";
- if (result & CommandLineParseHelpRequested)
- std::fputs(qPrintable(helpText(parser)), stdout);
- if (result & CommandLineParseError)
+ // Early parse the --qmake and --qtpaths options, because they are needed to determine the
+ // options that select/deselect Qt modules.
+ {
+ int result = parseEarlyArguments(QCoreApplication::arguments(), &options, &errorMessage);
+ if (result & CommandLineParseError) {
+ std::wcerr << "Error: " << errorMessage << "\n";
return 1;
- if (result & CommandLineParseHelpRequested)
- return 0;
+ }
}
const QMap<QString, QString> qtpathsVariables =
queryQtPaths(options.qtpathsBinary, &errorMessage);
const QString xSpec = qtpathsVariables.value(QStringLiteral("QMAKE_XSPEC"));
- options.platform = platformFromMkSpec(xSpec);
-
if (qtpathsVariables.isEmpty() || xSpec.isEmpty()
|| !qtpathsVariables.contains(QStringLiteral("QT_INSTALL_BINS"))) {
std::wcerr << "Unable to query qtpaths: " << errorMessage << '\n';
return 1;
}
+ options.platform = platformFromMkSpec(xSpec);
if (options.platform == UnknownPlatform) {
std::wcerr << "Unsupported platform " << xSpec << '\n';
return 1;
}
+ // Read the Qt module information from the Qt installation directory.
+ const QString modulesDir
+ = qtpathsVariables.value(QLatin1String("QT_INSTALL_ARCHDATA"))
+ + QLatin1String("/modules");
+ const QString translationsDir
+ = qtpathsVariables.value(QLatin1String("QT_INSTALL_TRANSLATIONS"));
+ if (!qtModuleEntries.populate(modulesDir, translationsDir, optVerboseLevel > 1,
+ &errorMessage)) {
+ std::wcerr << "Error: " << errorMessage << "\n";
+ return 1;
+ }
+ assignKnownModuleIds();
+
+ // Read the Qt plugin types information from the Qt installation directory.
+ PluginInformation pluginInfo{};
+ pluginInfo.generateAvailablePlugins(qtpathsVariables, options.platform);
+
+ // Parse the full command line.
+ {
+ QCommandLineParser parser;
+ QString errorMessage;
+ const int result = parseArguments(QCoreApplication::arguments(), &parser, &options, &errorMessage);
+ if (result & CommandLineParseError)
+ std::wcerr << errorMessage << "\n\n";
+ if (result & CommandLineVersionRequested) {
+ std::fputs(QT_VERSION_STR "\n", stdout);
+ return 0;
+ }
+ if (result & CommandLineParseHelpRequested)
+ std::fputs(qPrintable(helpText(parser, pluginInfo)), stdout);
+ if (result & CommandLineParseError)
+ return 1;
+ if (result & CommandLineParseHelpRequested)
+ return 0;
+ }
+
// Create directories
- if (!createDirectory(options.directory, &errorMessage)) {
+ if (!createDirectory(options.directory, &errorMessage, options.dryRun)) {
std::wcerr << errorMessage << '\n';
return 1;
}
if (!options.libraryDirectory.isEmpty() && options.libraryDirectory != options.directory
- && !createDirectory(options.libraryDirectory, &errorMessage)) {
+ && !createDirectory(options.libraryDirectory, &errorMessage, options.dryRun)) {
std::wcerr << errorMessage << '\n';
return 1;
}
- const DeployResult result = deploy(options, qtpathsVariables, &errorMessage);
+ const DeployResult result = deploy(options, qtpathsVariables, pluginInfo, &errorMessage);
if (!result) {
std::wcerr << errorMessage << '\n';
return 1;
}
- if (result.deployedQtLibraries & QtWebEngineCoreModule) {
- if (!deployWebEngineCore(qtpathsVariables, options, result.isDebug, &errorMessage)) {
+ if (result.deployedQtLibraries.test(QtWebEngineCoreModuleId)) {
+ if (!deployWebEngineCore(qtpathsVariables, pluginInfo, options, result.isDebug,
+ &errorMessage)) {
std::wcerr << errorMessage << '\n';
return 1;
}
diff --git a/src/tools/windeployqt/qmlutils.cpp b/src/tools/windeployqt/qmlutils.cpp
index 6eebf6d86e..a7e63e7470 100644
--- a/src/tools/windeployqt/qmlutils.cpp
+++ b/src/tools/windeployqt/qmlutils.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmlutils.h"
#include "utils.h"
@@ -39,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
bool operator==(const QmlImportScanResult::Module &m1, const QmlImportScanResult::Module &m2)
{
return m1.className.isEmpty() ? m1.name == m2.name : m1.className == m2.className;
@@ -48,9 +25,9 @@ bool operator==(const QmlImportScanResult::Module &m1, const QmlImportScanResult
QString QmlImportScanResult::Module::installPath(const QString &root) const
{
QString result = root;
- const int lastSlashPos = relativePath.lastIndexOf(QLatin1Char('/'));
+ const qsizetype lastSlashPos = relativePath.lastIndexOf(u'/');
if (lastSlashPos != -1) {
- result += QLatin1Char('/');
+ result += u'/';
result += QStringView{relativePath}.left(lastSlashPos);
}
return result;
@@ -90,7 +67,8 @@ static void findFileRecursion(const QDir &directory, Platform platform,
const QFileInfoList &subDirs = directory.entryInfoList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
for (const QFileInfo &subDirFi : subDirs) {
QDir subDirectory(subDirFi.absoluteFilePath());
- if (subDirectory.isReadable())
+ // Don't enter other QML modules when recursing!
+ if (subDirectory.isReadable() && !subDirectory.exists(QStringLiteral("qmldir")))
findFileRecursion(subDirectory, platform, debugMatchMode, matches);
}
}
@@ -121,14 +99,14 @@ QmlImportScanResult runQmlImportScanner(const QString &directory, const QStringL
if (data.isNull() ) {
*errorMessage = binary + QStringLiteral(" returned invalid JSON output: ")
+ jsonParseError.errorString() + QStringLiteral(" :\"")
- + QString::fromLocal8Bit(stdOut) + QLatin1Char('"');
+ + QString::fromLocal8Bit(stdOut) + u'"';
return result;
}
const QJsonArray array = data.array();
const int childCount = array.count();
for (int c = 0; c < childCount; ++c) {
const QJsonObject object = array.at(c).toObject();
- if (object.value(QStringLiteral("type")).toString() == QLatin1String("module")) {
+ if (object.value(QStringLiteral("type")).toString() == "module"_L1) {
const QString path = object.value(QStringLiteral("path")).toString();
if (!path.isEmpty()) {
QmlImportScanResult::Module module;
diff --git a/src/tools/windeployqt/qmlutils.h b/src/tools/windeployqt/qmlutils.h
index 572be7cab0..bff1fb3a9b 100644
--- a/src/tools/windeployqt/qmlutils.h
+++ b/src/tools/windeployqt/qmlutils.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QMLUTILS_H
#define QMLUTILS_H
diff --git a/src/tools/windeployqt/qtmoduleinfo.cpp b/src/tools/windeployqt/qtmoduleinfo.cpp
new file mode 100644
index 0000000000..b928a64478
--- /dev/null
+++ b/src/tools/windeployqt/qtmoduleinfo.cpp
@@ -0,0 +1,183 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "qtmoduleinfo.h"
+#include "utils.h"
+
+#include <QDirListing>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QDebug>
+
+#include <iostream>
+#include <algorithm>
+#include <unordered_map>
+
+using namespace Qt::StringLiterals;
+
+static QStringList toStringList(const QJsonArray &jsonArray)
+{
+ QStringList result;
+ for (const auto &item : jsonArray) {
+ if (item.isString())
+ result.append(item.toString());
+ }
+ return result;
+}
+
+struct TranslationCatalog
+{
+ QString name;
+ QStringList repositories;
+ QStringList modules;
+};
+
+using TranslationCatalogs = std::vector<TranslationCatalog>;
+
+static TranslationCatalogs readTranslationsCatalogs(const QString &translationsDir,
+ bool verbose,
+ QString *errorString)
+{
+ QFile file(translationsDir + QLatin1String("/catalogs.json"));
+ if (verbose) {
+ std::wcerr << "Trying to read translation catalogs from \""
+ << qUtf8Printable(file.fileName()) << "\".\n";
+ }
+ if (!file.open(QIODevice::ReadOnly)) {
+ *errorString = QLatin1String("Cannot open ") + file.fileName();
+ return {};
+ }
+
+ QJsonParseError jsonParseError;
+ QJsonDocument document = QJsonDocument::fromJson(file.readAll(), &jsonParseError);
+ if (jsonParseError.error != QJsonParseError::NoError) {
+ *errorString = jsonParseError.errorString();
+ return {};
+ }
+
+ if (!document.isArray()) {
+ *errorString = QLatin1String("Expected an array as root element of ") + file.fileName();
+ return {};
+ }
+
+ TranslationCatalogs catalogs;
+ for (const QJsonValueRef &item : document.array()) {
+ TranslationCatalog catalog;
+ catalog.name = item[QLatin1String("name")].toString();
+ catalog.repositories = toStringList(item[QLatin1String("repositories")].toArray());
+ catalog.modules = toStringList(item[QLatin1String("modules")].toArray());
+ if (verbose)
+ std::wcerr << "Found catalog \"" << qUtf8Printable(catalog.name) << "\".\n";
+ catalogs.emplace_back(std::move(catalog));
+ }
+
+ return catalogs;
+}
+
+static QtModule moduleFromJsonFile(const QString &filePath, QString *errorString)
+{
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ *errorString = QLatin1String("Cannot open ") + file.fileName();
+ return {};
+ }
+
+ QJsonParseError jsonParseError;
+ QJsonDocument document = QJsonDocument::fromJson(file.readAll(), &jsonParseError);
+ if (jsonParseError.error != QJsonParseError::NoError) {
+ *errorString = jsonParseError.errorString();
+ return {};
+ }
+
+ if (!document.isObject()) {
+ *errorString = QLatin1String("Expected an object as root element of ") + file.fileName();
+ return {};
+ }
+
+ const QJsonObject obj = document.object();
+ QtModule module;
+ module.name = "Qt6"_L1 + obj[QLatin1String("name")].toString();
+ module.repository = obj[QLatin1String("repository")].toString();
+ module.internal = obj[QLatin1String("internal")].toBool();
+ module.pluginTypes = toStringList(obj[QLatin1String("plugin_types")].toArray());
+ return module;
+}
+
+static void dump(const QtModule &module)
+{
+ std::wcerr << "Found module \"" << qUtf8Printable(module.name) << "\".\n";
+ if (!module.pluginTypes.isEmpty())
+ qDebug().nospace() << " plugin types: " << module.pluginTypes;
+ if (!module.translationCatalog.isEmpty())
+ qDebug().nospace() << " translation catalog: "<< module.translationCatalog;
+}
+
+bool QtModuleInfoStore::populate(const QString &modulesDir, const QString &translationsDir,
+ bool verbose, QString *errorString)
+{
+ const TranslationCatalogs catalogs = readTranslationsCatalogs(translationsDir, verbose,
+ errorString);
+ if (!errorString->isEmpty()) {
+ std::wcerr << "Warning: Translations will not be available due to the following error."
+ << std::endl << *errorString << std::endl;
+ errorString->clear();
+ }
+ std::unordered_map<QString, QString> moduleToCatalogMap;
+ std::unordered_map<QString, QString> repositoryToCatalogMap;
+ for (const TranslationCatalog &catalog : catalogs) {
+ for (const QString &module : catalog.modules) {
+ moduleToCatalogMap.insert(std::make_pair(module, catalog.name));
+ }
+ for (const QString &repository : catalog.repositories) {
+ repositoryToCatalogMap.insert(std::make_pair(repository, catalog.name));
+ }
+ }
+
+ // Read modules, and assign a bit as ID.
+ for (const auto &dirEntry : QDirListing(modulesDir, {u"*.json"_s}, QDir::Files)) {
+ QtModule module = moduleFromJsonFile(dirEntry.filePath(), errorString);
+ if (!errorString->isEmpty())
+ return false;
+ if (module.internal && module.name.endsWith(QStringLiteral("Private")))
+ module.name.chop(7);
+ module.id = modules.size();
+ if (module.id == QtModule::InvalidId) {
+ *errorString = "Internal Error: too many modules for ModuleBitset to hold."_L1;
+ return false;
+ }
+
+ {
+ auto it = moduleToCatalogMap.find(module.name);
+ if (it != moduleToCatalogMap.end())
+ module.translationCatalog = it->second;
+ }
+ if (module.translationCatalog.isEmpty()) {
+ auto it = repositoryToCatalogMap.find(module.repository);
+ if (it != repositoryToCatalogMap.end())
+ module.translationCatalog = it->second;
+ }
+ if (verbose)
+ dump(module);
+ modules.emplace_back(std::move(module));
+ }
+
+ return true;
+}
+
+const QtModule &QtModuleInfoStore::moduleById(size_t id) const
+{
+ return modules.at(id);
+}
+
+size_t QtModuleInfoStore::moduleIdForPluginType(const QString &pluginType) const
+{
+ auto moduleHasPluginType = [&pluginType] (const QtModule &module) {
+ return module.pluginTypes.contains(pluginType);
+ };
+
+ auto it = std::find_if(modules.begin(), modules.end(), moduleHasPluginType);
+ if (it != modules.end())
+ return it->id ;
+
+ return QtModule::InvalidId;
+}
diff --git a/src/tools/windeployqt/qtmoduleinfo.h b/src/tools/windeployqt/qtmoduleinfo.h
new file mode 100644
index 0000000000..b35403a090
--- /dev/null
+++ b/src/tools/windeployqt/qtmoduleinfo.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef QTMODULEINFO_H
+#define QTMODULEINFO_H
+
+#include <QString>
+#include <QStringList>
+
+#include <bitset>
+#include <vector>
+
+constexpr size_t ModuleBitsetSize = 1024;
+using ModuleBitset = std::bitset<ModuleBitsetSize>;
+
+struct QtModule
+{
+ static constexpr size_t InvalidId = ModuleBitsetSize - 1;
+ size_t id = InvalidId;
+ bool internal = false;
+ QString name;
+ QString repository;
+ QStringList pluginTypes;
+ QString translationCatalog;
+};
+
+inline bool contains(const ModuleBitset &modules, const QtModule &module)
+{
+ return modules.test(module.id);
+}
+
+class QtModuleInfoStore
+{
+public:
+ QtModuleInfoStore() = default;
+
+ bool populate(const QString &modulesDir, const QString &translationsDir, bool verbose,
+ QString *errorString);
+
+ size_t size() const { return modules.size(); }
+ std::vector<QtModule>::const_iterator begin() const { return modules.begin(); }
+ std::vector<QtModule>::const_iterator end() const { return modules.end(); }
+
+ const QtModule &moduleById(size_t id) const;
+ size_t moduleIdForPluginType(const QString &pluginType) const;
+
+private:
+ std::vector<QtModule> modules;
+};
+
+#endif
diff --git a/src/tools/windeployqt/qtplugininfo.cpp b/src/tools/windeployqt/qtplugininfo.cpp
new file mode 100644
index 0000000000..1deaa35f35
--- /dev/null
+++ b/src/tools/windeployqt/qtplugininfo.cpp
@@ -0,0 +1,100 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "qtplugininfo.h"
+
+#include <QDir>
+
+static PluginDetection determinePluginLibrary(const QDir &platformPluginDir, const QString &infix)
+{
+ // Use the platform plugin to determine which dlls are there (release/debug/both)
+ QString platformReleaseFilter(QStringLiteral("qwindows"));
+ if (!infix.isEmpty())
+ platformReleaseFilter += infix;
+ QString platformFilter = platformReleaseFilter + u'*';
+ platformFilter += sharedLibrarySuffix();
+
+ const QFileInfoList &dlls =
+ platformPluginDir.entryInfoList(QStringList(platformFilter), QDir::Files);
+ if (dlls.size() == 1) {
+ const QFileInfo dllFi = dlls.first();
+ const bool hasDebugDlls =
+ dllFi.fileName() == QString(platformReleaseFilter + sharedLibrarySuffix()) ? false
+ : true;
+ return (hasDebugDlls ? PluginDetection::DebugOnly : PluginDetection::ReleaseOnly);
+ } else {
+ return PluginDetection::DebugAndRelease;
+ }
+}
+
+static QStringList findPluginNames(const QDir &pluginDir, const PluginDetection libraryType,
+ const Platform &platform)
+{
+ QString errorMessage{};
+ QStringList result{};
+ QString filter{};
+ filter += u"*";
+ filter += sharedLibrarySuffix();
+
+ const QFileInfoList &dlls =
+ pluginDir.entryInfoList(QStringList(filter), QDir::Files, QDir::Name);
+
+ for (const QFileInfo &dllFi : dlls) {
+ QString plugin = dllFi.fileName();
+ const int dotIndex = plugin.lastIndexOf(u'.');
+ // We don't need the .dll for the name
+ plugin = plugin.first(dotIndex);
+
+ if (libraryType == PluginDetection::DebugAndRelease) {
+ bool isDebugDll{};
+ if (!readPeExecutable(dllFi.absoluteFilePath(), &errorMessage, 0, 0, &isDebugDll,
+ (platform == WindowsDesktopMinGW))) {
+ std::wcerr << "Warning: Unable to read "
+ << QDir::toNativeSeparators(dllFi.absoluteFilePath()) << ": "
+ << errorMessage;
+ }
+ if (isDebugDll && platformHasDebugSuffix(platform))
+ plugin.removeLast();
+ }
+ else if (libraryType == PluginDetection::DebugOnly)
+ plugin.removeLast();
+
+ if (!result.contains(plugin))
+ result.append(plugin);
+ }
+ return result;
+}
+
+bool PluginInformation::isTypeForPlugin(const QString &type, const QString &plugin) const
+{
+ return m_pluginMap.at(plugin) == type;
+}
+
+void PluginInformation::populatePluginToType(const QDir &pluginDir, const QStringList &plugins)
+{
+ for (const QString &plugin : plugins)
+ m_pluginMap.insert({ plugin, pluginDir.dirName() });
+}
+
+void PluginInformation::generateAvailablePlugins(const QMap<QString, QString> &qtPathsVariables,
+ const Platform &platform)
+{
+ const QDir pluginTypesDir(qtPathsVariables.value(QLatin1String("QT_INSTALL_PLUGINS")));
+ const QDir platformPluginDir(pluginTypesDir.absolutePath() + QStringLiteral("/platforms"));
+ const QString infix(qtPathsVariables.value(QLatin1String(qmakeInfixKey)));
+ const PluginDetection debugDetection = determinePluginLibrary(platformPluginDir, infix);
+
+ const QFileInfoList &pluginTypes =
+ pluginTypesDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ for (const QFileInfo &pluginType : pluginTypes) {
+ const QString pluginTypeName = pluginType.baseName();
+ m_typeMap.insert({ pluginTypeName, QStringList{} });
+ const QStringList plugins =
+ findPluginNames(pluginType.absoluteFilePath(), debugDetection, platform);
+ m_typeMap.at(pluginTypeName) = plugins;
+ populatePluginToType(pluginTypeName, plugins);
+ }
+ if (!m_typeMap.size() || !m_pluginMap.size())
+ std::wcerr << "Warning: could not parse available plugins properly, plugin "
+ "inclusion/exclusion options will not work\n";
+}
diff --git a/src/tools/windeployqt/qtplugininfo.h b/src/tools/windeployqt/qtplugininfo.h
new file mode 100644
index 0000000000..420b2b5e1a
--- /dev/null
+++ b/src/tools/windeployqt/qtplugininfo.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef QTPLUGININFO_H
+#define QTPLUGININFO_H
+
+#include "utils.h"
+
+#include <QString>
+#include <QStringList>
+
+#include <unordered_map>
+
+enum class PluginDetection
+{
+ DebugOnly,
+ ReleaseOnly,
+ DebugAndRelease
+};
+
+struct PluginSelections
+{
+ QStringList disabledPluginTypes;
+ QStringList enabledPluginTypes;
+ QStringList excludedPlugins;
+ QStringList includedPlugins;
+ bool includeSoftPlugins = false;
+};
+
+class PluginInformation
+{
+public:
+ PluginInformation() = default;
+
+ bool isTypeForPlugin(const QString &type, const QString &plugin) const;
+
+ void generateAvailablePlugins(const QMap<QString, QString> &qtPathsVariables,
+ const Platform &platform);
+ void populatePluginToType(const QDir &pluginDir, const QStringList &plugins);
+
+ const std::unordered_map<QString, QStringList> &typeMap() const { return m_typeMap; }
+
+private:
+ std::unordered_map<QString, QStringList> m_typeMap;
+ std::unordered_map<QString, QString> m_pluginMap;
+};
+
+#endif
diff --git a/src/tools/windeployqt/utils.cpp b/src/tools/windeployqt/utils.cpp
index bc52de924e..5141119254 100644
--- a/src/tools/windeployqt/utils.cpp
+++ b/src/tools/windeployqt/utils.cpp
@@ -1,33 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "utils.h"
-#include "elfreader.h"
#include <QtCore/QString>
#include <QtCore/QDebug>
@@ -40,6 +14,7 @@
#include <QtCore/QStandardPaths>
#if defined(Q_OS_WIN)
# include <QtCore/qt_windows.h>
+# include <QtCore/private/qsystemerror_p.h>
# include <shlwapi.h>
# include <delayimp.h>
#else // Q_OS_WIN
@@ -55,12 +30,14 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
int optVerboseLevel = 1;
bool isBuildDirectory(Platform platform, const QString &dirName)
{
return (platform.testFlag(Msvc) || platform.testFlag(ClangMsvc))
- && (dirName == QLatin1String("debug") || dirName == QLatin1String("release"));
+ && (dirName == "debug"_L1 || dirName == "release"_L1);
}
// Create a symbolic link by changing to the source directory to make sure the
@@ -84,7 +61,7 @@ bool createSymbolicLink(const QFileInfo &source, const QString &target, QString
return true;
}
-bool createDirectory(const QString &directory, QString *errorMessage)
+bool createDirectory(const QString &directory, QString *errorMessage, bool dryRun)
{
const QFileInfo fi(directory);
if (fi.isDir())
@@ -96,11 +73,13 @@ bool createDirectory(const QString &directory, QString *errorMessage)
}
if (optVerboseLevel)
std::wcout << "Creating " << QDir::toNativeSeparators(directory) << "...\n";
- QDir dir;
- if (!dir.mkpath(directory)) {
- *errorMessage = QString::fromLatin1("Could not create directory %1.").
- arg(QDir::toNativeSeparators(directory));
- return false;
+ if (!dryRun) {
+ QDir dir;
+ if (!dir.mkpath(directory)) {
+ *errorMessage = QString::fromLatin1("Could not create directory %1.")
+ .arg(QDir::toNativeSeparators(directory));
+ return false;
+ }
}
return true;
}
@@ -112,10 +91,10 @@ QStringList findSharedLibraries(const QDir &directory, Platform platform,
{
QString nameFilter = prefix;
if (nameFilter.isEmpty())
- nameFilter += QLatin1Char('*');
+ nameFilter += u'*';
if (debugMatchMode == MatchDebug && platformHasDebugSuffix(platform))
- nameFilter += QLatin1Char('d');
- nameFilter += sharedLibrarySuffix(platform);
+ nameFilter += u'd';
+ nameFilter += sharedLibrarySuffix();
QStringList result;
QString errorMessage;
const QFileInfoList &dlls = directory.entryInfoList(QStringList(nameFilter), QDir::Files);
@@ -139,22 +118,6 @@ QStringList findSharedLibraries(const QDir &directory, Platform platform,
}
#ifdef Q_OS_WIN
-QString winErrorMessage(unsigned long error)
-{
- QString rc = QString::fromLatin1("#%1: ").arg(error);
- char16_t *lpMsgBuf;
-
- const DWORD len = FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, error, 0, reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, NULL);
- if (len) {
- rc = QString::fromUtf16(lpMsgBuf, int(len));
- LocalFree(lpMsgBuf);
- } else {
- rc += QString::fromLatin1("<unknown error>");
- }
- return rc;
-}
// Case-Normalize file name via GetShortPathNameW()/GetLongPathNameW()
QString normalizeFileName(const QString &name)
@@ -172,10 +135,10 @@ QString normalizeFileName(const QString &name)
// Find a tool binary in the Windows SDK 8
QString findSdkTool(const QString &tool)
{
- QStringList paths = QString::fromLocal8Bit(qgetenv("PATH")).split(QLatin1Char(';'));
+ QStringList paths = QString::fromLocal8Bit(qgetenv("PATH")).split(u';');
const QByteArray sdkDir = qgetenv("WindowsSdkDir");
if (!sdkDir.isEmpty())
- paths.prepend(QDir::cleanPath(QString::fromLocal8Bit(sdkDir)) + QLatin1String("/Tools/x64"));
+ paths.prepend(QDir::cleanPath(QString::fromLocal8Bit(sdkDir)) + "/Tools/x64"_L1);
return QStandardPaths::findExecutable(tool, paths);
}
@@ -212,14 +175,14 @@ static inline void readTemporaryProcessFile(HANDLE handle, QByteArray *result)
static inline void appendToCommandLine(const QString &argument, QString *commandLine)
{
- const bool needsQuote = argument.contains(QLatin1Char(' '));
+ const bool needsQuote = argument.contains(u' ');
if (!commandLine->isEmpty())
- commandLine->append(QLatin1Char(' '));
+ commandLine->append(u' ');
if (needsQuote)
- commandLine->append(QLatin1Char('"'));
+ commandLine->append(u'"');
commandLine->append(argument);
if (needsQuote)
- commandLine->append(QLatin1Char('"'));
+ commandLine->append(u'"');
}
// runProcess: Run a command line process (replacement for QProcess which
@@ -244,7 +207,7 @@ bool runProcess(const QString &binary, const QStringList &args,
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
- const QChar backSlash = QLatin1Char('\\');
+ const QChar backSlash = u'\\';
QString nativeWorkingDir = QDir::toNativeSeparators(workingDirectory.isEmpty() ? QDir::currentPath() : workingDirectory);
if (!nativeWorkingDir.endsWith(backSlash))
nativeWorkingDir += backSlash;
@@ -286,8 +249,10 @@ bool runProcess(const QString &binary, const QStringList &args,
CloseHandle(si.hStdOutput);
if (stdErr)
CloseHandle(si.hStdError);
- if (errorMessage)
- *errorMessage = QStringLiteral("CreateProcessW failed: ") + winErrorMessage(GetLastError());
+ if (errorMessage) {
+ *errorMessage = QStringLiteral("CreateProcessW failed: ")
+ + QSystemError::windowsString();
+ }
return false;
}
@@ -317,8 +282,8 @@ static inline char *encodeFileName(const QString &f)
static inline char *tempFilePattern()
{
QString path = QDir::tempPath();
- if (!path.endsWith(QLatin1Char('/')))
- path += QLatin1Char('/');
+ if (!path.endsWith(u'/'))
+ path += u'/';
path += QStringLiteral("tmpXXXXXX");
return encodeFileName(path);
}
@@ -396,7 +361,7 @@ bool runProcess(const QString &binary, const QStringList &args,
char **argv = new char *[args.size() + 2]; // Create argv.
char **ap = argv;
*ap++ = encodeFileName(binary);
- for (const QString &a : qAsConst(args))
+ for (const QString &a : std::as_const(args))
*ap++ = encodeFileName(a);
*ap = 0;
@@ -458,24 +423,28 @@ const char *qmakeInfixKey = "QT_INFIX";
QMap<QString, QString> queryQtPaths(const QString &qtpathsBinary, QString *errorMessage)
{
const QString binary = !qtpathsBinary.isEmpty() ? qtpathsBinary : QStringLiteral("qtpaths");
+ const QString colonSpace = QStringLiteral(": ");
QByteArray stdOut;
QByteArray stdErr;
unsigned long exitCode = 0;
- if (!runProcess(binary, QStringList(QStringLiteral("-query")), QString(), &exitCode, &stdOut, &stdErr, errorMessage))
+ if (!runProcess(binary, QStringList(QStringLiteral("-query")), QString(), &exitCode, &stdOut,
+ &stdErr, errorMessage)) {
+ *errorMessage = QStringLiteral("Error running binary ") + binary + colonSpace + *errorMessage;
return QMap<QString, QString>();
+ }
if (exitCode) {
*errorMessage = binary + QStringLiteral(" returns ") + QString::number(exitCode)
- + QStringLiteral(": ") + QString::fromLocal8Bit(stdErr);
+ + colonSpace + QString::fromLocal8Bit(stdErr);
return QMap<QString, QString>();
}
- const QString output = QString::fromLocal8Bit(stdOut).trimmed().remove(QLatin1Char('\r'));
+ const QString output = QString::fromLocal8Bit(stdOut).trimmed().remove(u'\r');
QMap<QString, QString> result;
- const int size = output.size();
- for (int pos = 0; pos < size; ) {
- const int colonPos = output.indexOf(QLatin1Char(':'), pos);
+ const qsizetype size = output.size();
+ for (qsizetype pos = 0; pos < size; ) {
+ const qsizetype colonPos = output.indexOf(u':', pos);
if (colonPos < 0)
break;
- int endPos = output.indexOf(QLatin1Char('\n'), colonPos + 1);
+ qsizetype endPos = output.indexOf(u'\n', colonPos + 1);
if (endPos < 0)
endPos = size;
const QString key = output.mid(pos, colonPos - pos);
@@ -494,14 +463,14 @@ QMap<QString, QString> queryQtPaths(const QString &qtpathsBinary, QString *error
if (pos >= 0) {
const QString infix = QString::fromUtf8(line.right(line.size() - pos - 1).trimmed());
if (!infix.isEmpty())
- result.insert(QLatin1String(qmakeInfixKey), infix);
+ result.insert(QLatin1StringView(qmakeInfixKey), infix);
}
break;
}
}
} else {
std::wcerr << "Warning: Unable to read " << QDir::toNativeSeparators(qconfigPriFile.fileName())
- << ": " << qconfigPriFile.errorString()<< '\n';
+ << colonSpace << qconfigPriFile.errorString()<< '\n';
}
return result;
}
@@ -511,7 +480,7 @@ bool updateFile(const QString &sourceFileName, const QStringList &nameFilters,
const QString &targetDirectory, unsigned flags, JsonOutput *json, QString *errorMessage)
{
const QFileInfo sourceFileInfo(sourceFileName);
- const QString targetFileName = targetDirectory + QLatin1Char('/') + sourceFileInfo.fileName();
+ const QString targetFileName = targetDirectory + u'/' + sourceFileInfo.fileName();
if (optVerboseLevel > 1)
std::wcout << "Checking " << sourceFileName << ", " << targetFileName<< '\n';
@@ -587,37 +556,6 @@ bool updateFile(const QString &sourceFileName, const QStringList &nameFilters,
return true;
}
-bool readElfExecutable(const QString &elfExecutableFileName, QString *errorMessage,
- QStringList *dependentLibraries, unsigned *wordSize,
- bool *isDebug)
-{
- ElfReader elfReader(elfExecutableFileName);
- const ElfData data = elfReader.readHeaders();
- if (data.sectionHeaders.isEmpty()) {
- *errorMessage = QStringLiteral("Unable to read ELF binary \"")
- + QDir::toNativeSeparators(elfExecutableFileName) + QStringLiteral("\": ")
- + elfReader.errorString();
- return false;
- }
- if (wordSize)
- *wordSize = data.elfclass == Elf_ELFCLASS64 ? 64 : 32;
- if (dependentLibraries) {
- dependentLibraries->clear();
- const QList<QByteArray> libs = elfReader.dependencies();
- if (libs.isEmpty()) {
- *errorMessage = QStringLiteral("Unable to read dependenices of ELF binary \"")
- + QDir::toNativeSeparators(elfExecutableFileName) + QStringLiteral("\": ")
- + elfReader.errorString();
- return false;
- }
- for (const QByteArray &l : libs)
- dependentLibraries->push_back(QString::fromLocal8Bit(l));
- }
- if (isDebug)
- *isDebug = data.symbolsType != UnknownSymbols && data.symbolsType != NoSymbols;
- return true;
-}
-
#ifdef Q_OS_WIN
static inline QString stringFromRvaPtr(const void *rvaPtr)
@@ -736,48 +674,71 @@ enum MsvcDebugRuntimeResult { MsvcDebugRuntime, MsvcReleaseRuntime, NoMsvcRuntim
static inline MsvcDebugRuntimeResult checkMsvcDebugRuntime(const QStringList &dependentLibraries)
{
for (const QString &lib : dependentLibraries) {
- int pos = 0;
- if (lib.startsWith(QLatin1String("MSVCR"), Qt::CaseInsensitive)
- || lib.startsWith(QLatin1String("MSVCP"), Qt::CaseInsensitive)
- || lib.startsWith(QLatin1String("VCRUNTIME"), Qt::CaseInsensitive)) {
- int lastDotPos = lib.lastIndexOf(QLatin1Char('.'));
+ qsizetype pos = 0;
+ if (lib.startsWith("MSVCR"_L1, Qt::CaseInsensitive)
+ || lib.startsWith("MSVCP"_L1, Qt::CaseInsensitive)
+ || lib.startsWith("VCRUNTIME"_L1, Qt::CaseInsensitive)
+ || lib.startsWith("VCCORLIB"_L1, Qt::CaseInsensitive)
+ || lib.startsWith("CONCRT"_L1, Qt::CaseInsensitive)
+ || lib.startsWith("UCRTBASE"_L1, Qt::CaseInsensitive)) {
+ qsizetype lastDotPos = lib.lastIndexOf(u'.');
pos = -1 == lastDotPos ? 0 : lastDotPos - 1;
}
- if (pos > 0 && lib.contains(QLatin1String("_app"), Qt::CaseInsensitive))
- pos -= 4;
-
- if (pos) {
- return lib.at(pos).toLower() == QLatin1Char('d')
- ? MsvcDebugRuntime : MsvcReleaseRuntime;
+ if (pos > 0) {
+ const auto removeExtraSuffix = [&lib, &pos](const QString &suffix) -> void {
+ if (lib.contains(suffix, Qt::CaseInsensitive))
+ pos -= suffix.size();
+ };
+ removeExtraSuffix("_app"_L1);
+ removeExtraSuffix("_atomic_wait"_L1);
+ removeExtraSuffix("_codecvt_ids"_L1);
}
+
+ if (pos)
+ return lib.at(pos).toLower() == u'd' ? MsvcDebugRuntime : MsvcReleaseRuntime;
}
return NoMsvcRuntime;
}
template <class ImageNtHeader>
+inline QStringList determineDependentLibs(const ImageNtHeader *nth, const void *fileMemory,
+ QString *errorMessage)
+{
+ return readImportSections(nth, fileMemory, errorMessage);
+}
+
+template <class ImageNtHeader>
+inline bool determineDebug(const ImageNtHeader *nth, const void *fileMemory,
+ QStringList *dependentLibrariesIn, QString *errorMessage)
+{
+ if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
+ return false;
+
+ const QStringList dependentLibraries = dependentLibrariesIn != nullptr ?
+ *dependentLibrariesIn :
+ determineDependentLibs(nth, fileMemory, errorMessage);
+
+ const bool hasDebugEntry = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ // When an MSVC debug entry is present, check whether the debug runtime
+ // is actually used to detect -release / -force-debug-info builds.
+ const MsvcDebugRuntimeResult msvcrt = checkMsvcDebugRuntime(dependentLibraries);
+ if (msvcrt == NoMsvcRuntime)
+ return hasDebugEntry;
+ else
+ return hasDebugEntry && msvcrt == MsvcDebugRuntime;
+}
+
+template <class ImageNtHeader>
inline void determineDebugAndDependentLibs(const ImageNtHeader *nth, const void *fileMemory,
- bool isMinGW,
QStringList *dependentLibrariesIn,
bool *isDebugIn, QString *errorMessage)
{
- const bool hasDebugEntry = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
- QStringList dependentLibraries;
- if (dependentLibrariesIn || (isDebugIn != nullptr && hasDebugEntry && !isMinGW))
- dependentLibraries = readImportSections(nth, fileMemory, errorMessage);
-
if (dependentLibrariesIn)
- *dependentLibrariesIn = dependentLibraries;
- if (isDebugIn != nullptr) {
- if (isMinGW) {
- // Use logic that's used e.g. in objdump / pfd library
- *isDebugIn = !(nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
- } else {
- // When an MSVC debug entry is present, check whether the debug runtime
- // is actually used to detect -release / -force-debug-info builds.
- *isDebugIn = hasDebugEntry && checkMsvcDebugRuntime(dependentLibraries) != MsvcReleaseRuntime;
- }
- }
+ *dependentLibrariesIn = determineDependentLibs(nth, fileMemory, errorMessage);
+
+ if (isDebugIn)
+ *isDebugIn = determineDebug(nth, fileMemory, dependentLibrariesIn, errorMessage);
}
// Read a PE executable and determine dependent libraries, word size
@@ -803,19 +764,22 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage
hFile = CreateFile(reinterpret_cast<const WCHAR*>(peExecutableFileName.utf16()), GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {
- *errorMessage = QString::fromLatin1("Cannot open '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
+ *errorMessage = QString::fromLatin1("Cannot open '%1': %2")
+ .arg(peExecutableFileName, QSystemError::windowsString());
break;
}
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hFileMap == NULL) {
- *errorMessage = QString::fromLatin1("Cannot create file mapping of '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
+ *errorMessage = QString::fromLatin1("Cannot create file mapping of '%1': %2")
+ .arg(peExecutableFileName, QSystemError::windowsString());
break;
}
fileMemory = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
if (!fileMemory) {
- *errorMessage = QString::fromLatin1("Cannot map '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
+ *errorMessage = QString::fromLatin1("Cannot map '%1': %2")
+ .arg(peExecutableFileName, QSystemError::windowsString());
break;
}
@@ -828,10 +792,10 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage
*wordSizeIn = wordSize;
if (wordSize == 32) {
determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS32 *>(ntHeaders),
- fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage);
+ fileMemory, dependentLibrariesIn, isDebugIn, errorMessage);
} else {
determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders),
- fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage);
+ fileMemory, dependentLibrariesIn, isDebugIn, errorMessage);
}
if (machineArchIn)
@@ -846,7 +810,7 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage
if (dependentLibrariesIn) {
std::wcout << ", dependent libraries: ";
if (optVerboseLevel > 2)
- std::wcout << dependentLibrariesIn->join(QLatin1Char(' '));
+ std::wcout << dependentLibrariesIn->join(u' ');
else
std::wcout << dependentLibrariesIn->size();
}
@@ -871,7 +835,7 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage
QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wordSize)
{
const QString prefix = QStringLiteral("D3Dcompiler_");
- const QString suffix = QLatin1String(windowsSharedLibrarySuffix);
+ const QString suffix = QLatin1StringView(windowsSharedLibrarySuffix);
// Get the DLL from Kit 8.0 onwards
const QString kitDir = QString::fromLocal8Bit(qgetenv("WindowsSdkDir"));
if (!kitDir.isEmpty()) {
@@ -883,7 +847,7 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor
}
QDir redistDir(redistDirPath);
if (redistDir.exists()) {
- const QFileInfoList files = redistDir.entryInfoList(QStringList(prefix + QLatin1Char('*') + suffix), QDir::Files);
+ const QFileInfoList files = redistDir.entryInfoList(QStringList(prefix + u'*' + suffix), QDir::Files);
if (!files.isEmpty())
return files.front().absoluteFilePath();
}
@@ -893,8 +857,8 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor
candidateVersions.append(prefix + QString::number(i) + suffix);
// Check the bin directory of the Qt SDK (in case it is shadowed by the
// Windows system directory in PATH).
- for (const QString &candidate : qAsConst(candidateVersions)) {
- const QFileInfo fi(qtBinDir + QLatin1Char('/') + candidate);
+ for (const QString &candidate : std::as_const(candidateVersions)) {
+ const QFileInfo fi(qtBinDir + u'/' + candidate);
if (fi.isFile())
return fi.absoluteFilePath();
}
@@ -902,7 +866,7 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor
if (platform.testFlag(IntelBased)) {
QString errorMessage;
unsigned detectedWordSize;
- for (const QString &candidate : qAsConst(candidateVersions)) {
+ for (const QString &candidate : std::as_const(candidateVersions)) {
const QString dll = findInPath(candidate);
if (!dll.isEmpty()
&& readPeExecutable(dll, &errorMessage, 0, &detectedWordSize, 0)
@@ -914,6 +878,53 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor
return QString();
}
+QStringList findDxc(Platform platform, const QString &qtBinDir, unsigned wordSize)
+{
+ QStringList results;
+ const QString kitDir = QString::fromLocal8Bit(qgetenv("WindowsSdkDir"));
+ const QString suffix = QLatin1StringView(windowsSharedLibrarySuffix);
+ for (QString prefix : { QStringLiteral("dxcompiler"), QStringLiteral("dxil") }) {
+ QString name = prefix + suffix;
+ if (!kitDir.isEmpty()) {
+ QString redistDirPath = QDir::cleanPath(kitDir) + QStringLiteral("/Redist/D3D/");
+ if (platform.testFlag(ArmBased)) {
+ redistDirPath += wordSize == 32 ? QStringLiteral("arm") : QStringLiteral("arm64");
+ } else {
+ redistDirPath += wordSize == 32 ? QStringLiteral("x86") : QStringLiteral("x64");
+ }
+ QDir redistDir(redistDirPath);
+ if (redistDir.exists()) {
+ const QFileInfoList files = redistDir.entryInfoList(QStringList(prefix + u'*' + suffix), QDir::Files);
+ if (!files.isEmpty()) {
+ results.append(files.front().absoluteFilePath());
+ continue;
+ }
+ }
+ }
+ // Check the bin directory of the Qt SDK (in case it is shadowed by the
+ // Windows system directory in PATH).
+ const QFileInfo fi(qtBinDir + u'/' + name);
+ if (fi.isFile()) {
+ results.append(fi.absoluteFilePath());
+ continue;
+ }
+ // Try to find it in the PATH (e.g. the Vulkan SDK ships these, even if Windows itself doesn't).
+ if (platform.testFlag(IntelBased)) {
+ QString errorMessage;
+ unsigned detectedWordSize;
+ const QString dll = findInPath(name);
+ if (!dll.isEmpty()
+ && readPeExecutable(dll, &errorMessage, 0, &detectedWordSize, 0)
+ && detectedWordSize == wordSize)
+ {
+ results.append(dll);
+ continue;
+ }
+ }
+ }
+ return results;
+}
+
#else // Q_OS_WIN
bool readPeExecutable(const QString &, QString *errorMessage,
@@ -928,6 +939,11 @@ QString findD3dCompiler(Platform, const QString &, unsigned)
return QString();
}
+QStringList findDxc(Platform, const QString &, unsigned)
+{
+ return QStringList();
+}
+
#endif // !Q_OS_WIN
// Search for "qt_prfxpath=xxxx" in \a path, and replace it with "qt_prfxpath=."
diff --git a/src/tools/windeployqt/utils.h b/src/tools/windeployqt/utils.h
index 0fe3a6948f..2c7cd79bf0 100644
--- a/src/tools/windeployqt/utils.h
+++ b/src/tools/windeployqt/utils.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef UTILS_H
#define UTILS_H
@@ -45,7 +20,6 @@ QT_BEGIN_NAMESPACE
enum PlatformFlag {
// OS
WindowsBased = 0x00001,
- UnixBased = 0x00002,
// CPU
IntelBased = 0x00010,
ArmBased = 0x00020,
@@ -59,7 +33,6 @@ enum PlatformFlag {
WindowsDesktopMinGW = WindowsBased + IntelBased + MinGW,
WindowsDesktopClangMsvc = WindowsBased + IntelBased + ClangMsvc,
WindowsDesktopClangMinGW = WindowsBased + IntelBased + ClangMinGW,
- Unix = UnixBased,
UnknownPlatform
};
@@ -93,7 +66,7 @@ inline std::wostream &operator<<(std::wostream &str, const QString &s)
// Container class for JSON output
class JsonOutput
{
- using SourceTargetMapping = QPair<QString, QString>;
+ using SourceTargetMapping = std::pair<QString, QString>;
using SourceTargetMappings = QList<SourceTargetMapping>;
public:
@@ -162,13 +135,12 @@ inline QString normalizeFileName(const QString &name) { return name; }
#endif // !Q_OS_WIN
static const char windowsSharedLibrarySuffix[] = ".dll";
-static const char unixSharedLibrarySuffix[] = ".so";
-inline QString sharedLibrarySuffix(Platform platform) { return QLatin1String((platform & WindowsBased) ? windowsSharedLibrarySuffix : unixSharedLibrarySuffix); }
+inline QString sharedLibrarySuffix() { return QLatin1StringView(windowsSharedLibrarySuffix); }
bool isBuildDirectory(Platform platform, const QString &dirName);
bool createSymbolicLink(const QFileInfo &source, const QString &target, QString *errorMessage);
-bool createDirectory(const QString &directory, QString *errorMessage);
+bool createDirectory(const QString &directory, QString *errorMessage, bool dryRun);
QString findInPath(const QString &file);
extern const char *qmakeInfixKey; // Fake key containing the libinfix
@@ -195,19 +167,6 @@ bool runProcess(const QString &binary, const QStringList &args,
bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage,
QStringList *dependentLibraries = 0, unsigned *wordSize = 0,
bool *isDebug = 0, bool isMinGW = false, unsigned short *machineArch = nullptr);
-bool readElfExecutable(const QString &elfExecutableFileName, QString *errorMessage,
- QStringList *dependentLibraries = 0, unsigned *wordSize = 0,
- bool *isDebug = 0);
-
-inline bool readExecutable(const QString &executableFileName, Platform platform,
- QString *errorMessage, QStringList *dependentLibraries = 0,
- unsigned *wordSize = 0, bool *isDebug = 0, unsigned short *machineArch = nullptr)
-{
- return platform == Unix ?
- readElfExecutable(executableFileName, errorMessage, dependentLibraries, wordSize, isDebug) :
- readPeExecutable(executableFileName, errorMessage, dependentLibraries, wordSize, isDebug,
- (platform == WindowsDesktopMinGW), machineArch);
-}
#ifdef Q_OS_WIN
# if !defined(IMAGE_FILE_MACHINE_ARM64)
@@ -218,14 +177,15 @@ QString getArchString (unsigned short machineArch);
// Return dependent modules of executable files.
-inline QStringList findDependentLibraries(const QString &executableFileName, Platform platform, QString *errorMessage)
+inline QStringList findDependentLibraries(const QString &executableFileName, QString *errorMessage)
{
QStringList result;
- readExecutable(executableFileName, platform, errorMessage, &result);
+ readPeExecutable(executableFileName, errorMessage, &result);
return result;
}
QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wordSize);
+QStringList findDxc(Platform platform, const QString &qtBinDir, unsigned wordSize);
bool patchQtCore(const QString &path, QString *errorMessage);
@@ -249,7 +209,7 @@ bool updateFile(const QString &sourceFileName,
QString *errorMessage)
{
const QFileInfo sourceFileInfo(sourceFileName);
- const QString targetFileName = targetDirectory + QLatin1Char('/') + sourceFileInfo.fileName();
+ const QString targetFileName = targetDirectory + u'/' + sourceFileInfo.fileName();
if (optVerboseLevel > 1)
std::wcout << "Checking " << sourceFileName << ", " << targetFileName << '\n';
@@ -263,7 +223,7 @@ bool updateFile(const QString &sourceFileName,
if (sourceFileInfo.isSymLink()) {
const QString sourcePath = sourceFileInfo.symLinkTarget();
const QString relativeSource = QDir(sourceFileInfo.absolutePath()).relativeFilePath(sourcePath);
- if (relativeSource.contains(QLatin1Char('/'))) {
+ if (relativeSource.contains(u'/')) {
*errorMessage = QString::fromLatin1("Symbolic links across directories are not supported (%1).")
.arg(QDir::toNativeSeparators(sourceFileName));
return false;
@@ -289,11 +249,11 @@ bool updateFile(const QString &sourceFileName,
return false;
}
} // target symbolic link exists
- return createSymbolicLink(QFileInfo(targetDirectory + QLatin1Char('/') + relativeSource), sourceFileInfo.fileName(), errorMessage);
+ return createSymbolicLink(QFileInfo(targetDirectory + u'/' + relativeSource), sourceFileInfo.fileName(), errorMessage);
} // Source is symbolic link
if (sourceFileInfo.isDir()) {
- if ((flags & SkipQmlDesignerSpecificsDirectories) && sourceFileInfo.fileName() == QLatin1String("designer")) {
+ if ((flags & SkipQmlDesignerSpecificsDirectories) && sourceFileInfo.fileName() == QLatin1StringView("designer")) {
if (optVerboseLevel)
std::wcout << "Skipping " << QDir::toNativeSeparators(sourceFileName) << ".\n";
return true;
@@ -323,13 +283,13 @@ bool updateFile(const QString &sourceFileName,
const QStringList allEntries = directoryFileEntryFunction(dir) + dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QString &entry : allEntries)
- if (!updateFile(sourceFileName + QLatin1Char('/') + entry, directoryFileEntryFunction, targetFileName, flags, json, errorMessage))
+ if (!updateFile(sourceFileName + u'/' + entry, directoryFileEntryFunction, targetFileName, flags, json, errorMessage))
return false;
// Remove empty directories, for example QML import folders for which the filter did not match.
if (created && (flags & RemoveEmptyQmlDirectories)) {
QDir d(targetFileName);
const QStringList entries = d.entryList(QStringList(), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- if (entries.isEmpty() || (entries.size() == 1 && entries.first() == QLatin1String("qmldir"))) {
+ if (entries.isEmpty() || (entries.size() == 1 && entries.first() == QLatin1StringView("qmldir"))) {
if (!d.removeRecursively()) {
*errorMessage = QString::fromLatin1("Cannot remove empty directory %1.")
.arg(QDir::toNativeSeparators(targetFileName));